Changeset 88255 in vbox
- Timestamp:
- Mar 23, 2021 8:43:58 AM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 143458
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/pdmaudioifs.h
r88253 r88255 1770 1770 * Returns the amount which is writable to the audio (output) stream. 1771 1771 * 1772 * @returns For non-raw layout streams: Number of writable bytes. 1773 * for raw layout streams : Number of writable audio frames. 1772 * @returns Number of writable bytes. 1774 1773 * @param pInterface Pointer to the interface structure containing the called function pointer. 1775 1774 * @param pStream Pointer to audio stream. -
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r88253 r88255 1582 1582 1583 1583 /** 1584 * Worker for drvAudioStreamPlay. 1585 */ 1586 static int drvAudioStreamPlayLocked(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcFramesPlayed) 1587 { 1588 /* 1589 * Zero the frame count so we can return at will. 1590 */ 1591 *pcFramesPlayed = 0; 1592 1593 PDMAUDIOSTREAMSTS fStrmStatus = pStream->fStatus; 1594 #ifdef LOG_ENABLED 1595 char szStreamSts[DRVAUDIO_STATUS_STR_MAX]; 1596 #endif 1597 Log3Func(("[%s] Start fStatus=%s\n", pStream->szName, dbgAudioStreamStatusToStr(szStreamSts, fStrmStatus))); 1598 1599 /* 1600 * Operational? 1601 */ 1602 if (pThis->pHostDrvAudio) 1603 { /* likely? */ } 1604 else 1605 return VERR_PDM_NO_ATTACHED_DRIVER; 1606 1607 if ( pThis->Out.fEnabled 1608 && PDMAudioStrmStatusIsReady(fStrmStatus)) 1609 { /* likely? */ } 1610 else 1611 return VERR_AUDIO_STREAM_NOT_READY; 1612 1613 1614 /* 1615 * 1616 */ 1617 const uint32_t cFramesLive = AudioMixBufLive(&pStream->Host.MixBuf); 1618 const uint64_t tsDeltaPlayedCapturedNs = RTTimeNanoTS() - pStream->tsLastPlayedCapturedNs; 1619 const uint32_t cFramesPassedReal = PDMAudioPropsNanoToFrames(&pStream->Host.Cfg.Props, tsDeltaPlayedCapturedNs); 1620 1621 Log3Func(("[%s] Last played %'RU64 ns ago; filled with %u frm / %RU64 ms / %RU8%% total%s\n", 1622 pStream->szName, tsDeltaPlayedCapturedNs, cFramesLive, 1623 PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesLive), 1624 (100 * cFramesLive) / AudioMixBufSize(&pStream->Host.MixBuf), pStream->fThresholdReached ? "" : ", pre-buffering")); 1625 1626 /* 1627 * Restart pre-buffering if we're having a buffer-underrun. 1628 */ 1629 if ( cFramesLive != 0 /* no underrun */ 1630 || !pStream->fThresholdReached /* or still pre-buffering. */) 1631 { /* likely */ } 1632 else 1633 { 1634 LogRel2(("Audio: Buffer underrun for stream '%s' occurred (%RU64ms passed)\n", 1635 pStream->szName, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesPassedReal))); 1636 1637 if (pStream->Host.Cfg.Backend.cFramesPreBuffering) /* Any pre-buffering configured? */ 1638 { 1639 /* Enter pre-buffering stage again. */ 1640 pStream->fThresholdReached = false; 1641 } 1642 } 1643 1644 /* 1645 * Work the pre-buffering. 1646 * 1647 * This is straight forward, the backend 1648 */ 1649 bool fJustStarted = false; 1650 if (pStream->fThresholdReached) 1651 { /* not-prebuffering, likely after a while at least */ } 1652 else 1653 { 1654 /* 1655 * Did we reach the backend's playback (pre-buffering) threshold? 1656 * Can be 0 if no pre-buffering desired. 1657 */ 1658 if (cFramesLive >= pStream->Host.Cfg.Backend.cFramesPreBuffering) 1659 { 1660 LogRel2(("Audio: Stream '%s' buffering complete\n", pStream->szName)); 1661 Log3Func(("[%s] Dbg: Buffering complete\n", pStream->szName)); 1662 pStream->fThresholdReached = fJustStarted = true; 1663 } 1664 /* 1665 * Some audio files are shorter than the pre-buffering level (e.g. the 1666 * "click" Explorer sounds on some Windows guests), so make sure that we 1667 * also play those by checking if the stream already is pending disable 1668 * mode, even if we didn't hit the pre-buffering watermark yet. 1669 * 1670 * Try play "Windows Navigation Start.wav" on Windows 7 (2824 samples). 1671 */ 1672 else if ( cFramesLive > 0 1673 && (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE)) 1674 { 1675 LogRel2(("Audio: Stream '%s' buffering complete (short sound)\n", pStream->szName)); 1676 Log3Func(("[%s] Dbg: Buffering complete (short)\n", pStream->szName)); 1677 pStream->fThresholdReached = fJustStarted = true; 1678 } 1679 /* 1680 * Not yet, so still buffering audio data. 1681 */ 1682 else 1683 { 1684 LogRel2(("Audio: Stream '%s' is buffering (%RU8%% complete)...\n", 1685 pStream->szName, (100 * cFramesLive) / pStream->Host.Cfg.Backend.cFramesPreBuffering)); 1686 return VINF_SUCCESS; 1687 } 1688 } 1689 1690 /* 1691 * Figure out how much to play now. 1692 * 1693 * The algorithm here is a litte dubious. The first time we get here after 1694 * pre-buffering is complete, we write one host DMA period wort of data to 1695 * the host audio driver. Then we refuse to write any more till one guest 1696 * device DMA period has elapsed, but when then we try to write as much 1697 * as we can to the host device driver. 1698 */ 1699 uint32_t cbWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream->pvBackend); 1700 uint32_t cFramesWritable = PDMAUDIOPCMPROPS_B2F(&pStream->Host.Cfg.Props, cbWritable); 1701 uint32_t cFramesToPlay; 1702 if (!fJustStarted) 1703 cFramesToPlay = 0; 1704 else 1705 cFramesToPlay = RT_MIN(cFramesWritable, pStream->Host.Cfg.Backend.cFramesPeriod); 1706 if (!cFramesToPlay) 1707 { 1708 /* Did we reach/pass (in real time) the device scheduling slot? 1709 * Play as much as we can write to the backend then. */ 1710 if (cFramesPassedReal >= PDMAudioPropsMilliToFrames(&pStream->Host.Cfg.Props, pStream->Guest.Cfg.Device.cMsSchedulingHint)) 1711 cFramesToPlay = cFramesWritable; 1712 } 1713 1714 if (cFramesToPlay > cFramesLive) /* Don't try to play more than available. */ 1715 cFramesToPlay = cFramesLive; 1716 1717 Log3Func(("[%s] Playing %RU32 frames (%RU64 ms), now filled with %RU64 ms -- %RU8%%\n", 1718 pStream->szName, cFramesToPlay, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesToPlay), 1719 PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, AudioMixBufUsed(&pStream->Host.MixBuf)), 1720 AudioMixBufUsed(&pStream->Host.MixBuf) * 100 / AudioMixBufSize(&pStream->Host.MixBuf))); 1721 1722 /* 1723 * Do the playing if we decided to play something. 1724 */ 1725 int rc = VINF_SUCCESS; 1726 if (cFramesToPlay) 1727 { 1728 if (pThis->pHostDrvAudio->pfnStreamPlayBegin) 1729 pThis->pHostDrvAudio->pfnStreamPlayBegin(pThis->pHostDrvAudio, pStream->pvBackend); 1730 1731 /** @todo r=bird: I don't honestly see any difference in interleaved, 1732 * non-interrleaved, raw, complicate, or whatever frame format we're 1733 * dealing with here. We'll be formatting a chunk of audio data and feed 1734 * it to the backend, the formatting is taken care of by the mixer and 1735 * we don't really care about the format anywhere here. 1736 * 1737 * Raw audio is just stereo S64, btw. Since drvAudioStreamPlayRaw 1738 * actually copies the mixer data instead of accessing the internal mixer 1739 * buffer directly, there is no advantage to having separate code paths 1740 * here. It only leads to more incomplete crappy code (I find the code 1741 * quality quite appaling, given the amount of time spent on it). 1742 * 1743 * What's more, I think the non-interleaved designation here is wrong 1744 * anyway. Non-interleaved means a stereo chunk of 8 frames is 1745 * formatted: 1746 * - LLLLLLLLRRRRRRRR 1747 * whereas I'm pretty darn sure we do: 1748 * - LRLRLRLRLRLRLRLR 1749 * given that the mixer doesn't know how to output the former. See the 1750 * audioMixBufConvTo##a_Name##Stereo() code, it clearly output LR pairs. 1751 * 1752 * https://stackoverflow.com/questions/17879933/whats-the-interleaved-audio 1753 */ 1754 if (RT_LIKELY(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED)) 1755 rc = drvAudioStreamPlayNonInterleaved(pThis, pStream, cFramesToPlay, pcFramesPlayed); 1756 else if (pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW) 1757 rc = drvAudioStreamPlayRaw(pThis, pStream, cFramesToPlay, pcFramesPlayed); 1758 else 1759 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED); 1760 1761 if (pThis->pHostDrvAudio->pfnStreamPlayEnd) 1762 pThis->pHostDrvAudio->pfnStreamPlayEnd(pThis->pHostDrvAudio, pStream->pvBackend); 1763 1764 pStream->tsLastPlayedCapturedNs = RTTimeNanoTS(); 1765 } 1766 1767 Log3Func(("[%s] SchedHint=%RU32 ms (%RU32 fr) Passed=%RU64 ms (%RU32 fr) Live=%RU32 fr (%RU64 ms) Period=%RU32 fr (%RU64 ms) Writable=%RU32 fr (%RU64 ms) -> ToPlay=%RU32 fr (%RU64 ms) Played=%RU32 fr (%RU64 ms)%s\n", 1768 pStream->szName, pStream->Guest.Cfg.Device.cMsSchedulingHint, 1769 PDMAudioPropsMilliToFrames(&pStream->Host.Cfg.Props, pStream->Guest.Cfg.Device.cMsSchedulingHint), 1770 PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesPassedReal), cFramesPassedReal, 1771 cFramesLive, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesLive), 1772 pStream->Host.Cfg.Backend.cFramesPeriod, 1773 PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, pStream->Host.Cfg.Backend.cFramesPeriod), 1774 cFramesWritable, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesWritable), 1775 cFramesToPlay, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesToPlay), 1776 *pcFramesPlayed, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, *pcFramesPlayed), 1777 fJustStarted ? "just-started" : "")); 1778 1779 if (RT_SUCCESS(rc)) 1780 { 1781 AudioMixBufFinish(&pStream->Host.MixBuf, *pcFramesPlayed); 1782 1783 STAM_PROFILE_ADV_STOP(&pThis->Stats.DelayOut, out); 1784 STAM_COUNTER_ADD(&pThis->Stats.TotalFramesOut, *pcFramesPlayed); 1785 STAM_COUNTER_ADD(&pStream->Out.Stats.TotalFramesPlayed, *pcFramesPlayed); 1786 STAM_COUNTER_INC(&pStream->Out.Stats.TotalTimesPlayed); 1787 } 1788 1789 Log3Func(("[%s] End fStatus=%s, cFramesLive=%RU32, cfPlayedTotal=%RU32, rc=%Rrc\n", pStream->szName, 1790 dbgAudioStreamStatusToStr(szStreamSts, fStrmStatus), AudioMixBufLive(&pStream->Host.MixBuf), *pcFramesPlayed, rc)); 1791 return rc; 1792 } 1793 1794 1795 /** 1584 1796 * @interface_method_impl{PDMIAUDIOCONNECTOR,pfnStreamPlay} 1585 1797 */ … … 1593 1805 ("Stream '%s' is not an output stream and therefore cannot be played back (direction is 0x%x)\n", 1594 1806 pStream->szName, pStream->enmDir)); 1807 1595 1808 int rc = RTCritSectEnter(&pThis->CritSect); 1596 1809 AssertRCReturn(rc, rc); 1597 1810 1598 uint32_t cfPlayedTotal = 0; 1599 1600 PDMAUDIOSTREAMSTS fStrmStatus = pStream->fStatus; 1601 #ifdef LOG_ENABLED 1602 char szStreamSts[DRVAUDIO_STATUS_STR_MAX]; 1603 #endif 1604 Log3Func(("[%s] Start fStatus=%s\n", pStream->szName, dbgAudioStreamStatusToStr(szStreamSts, fStrmStatus))); 1605 1606 do /* No, this isn't a loop either. sigh. */ 1607 { 1608 if (!pThis->pHostDrvAudio) 1609 { 1610 rc = VERR_PDM_NO_ATTACHED_DRIVER; 1611 break; 1612 } 1613 1614 if ( !pThis->Out.fEnabled 1615 || !PDMAudioStrmStatusIsReady(fStrmStatus)) 1616 { 1617 rc = VERR_AUDIO_STREAM_NOT_READY; 1618 break; 1619 } 1620 1621 const uint32_t cFramesLive = AudioMixBufLive(&pStream->Host.MixBuf); 1622 #ifdef LOG_ENABLED 1623 const uint8_t uLivePercent = (100 * cFramesLive) / AudioMixBufSize(&pStream->Host.MixBuf); 1624 #endif 1625 const uint64_t tsDeltaPlayedCapturedNs = RTTimeNanoTS() - pStream->tsLastPlayedCapturedNs; 1626 const uint32_t cfPassedReal = PDMAudioPropsNanoToFrames(&pStream->Host.Cfg.Props, tsDeltaPlayedCapturedNs); 1627 1628 const uint32_t cFramesPeriod = pStream->Host.Cfg.Backend.cFramesPeriod; 1629 1630 Log3Func(("[%s] Last played %RU64ns (%RU64ms), filled with %RU64ms (%RU8%%) total (fThresholdReached=%RTbool)\n", 1631 pStream->szName, tsDeltaPlayedCapturedNs, tsDeltaPlayedCapturedNs / RT_NS_1MS_64, 1632 PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesLive), uLivePercent, pStream->fThresholdReached)); 1633 1634 if ( pStream->fThresholdReached /* Has the treshold been reached (e.g. are we in playing stage) ... */ 1635 && cFramesLive == 0) /* ... and we now have no live samples to process? */ 1636 { 1637 LogRel2(("Audio: Buffer underrun for stream '%s' occurred (%RU64ms passed)\n", 1638 pStream->szName, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cfPassedReal))); 1639 1640 if (pStream->Host.Cfg.Backend.cFramesPreBuffering) /* Any pre-buffering configured? */ 1641 { 1642 /* Enter pre-buffering stage again. */ 1643 pStream->fThresholdReached = false; 1644 } 1645 } 1646 1647 bool fDoPlay = pStream->fThresholdReached; 1648 bool fJustStarted = false; 1649 if (!fDoPlay) 1650 { 1651 /* Did we reach the backend's playback (pre-buffering) threshold? Can be 0 if no threshold set. */ 1652 if (cFramesLive >= pStream->Host.Cfg.Backend.cFramesPreBuffering) 1653 { 1654 LogRel2(("Audio: Stream '%s' buffering complete\n", pStream->szName)); 1655 Log3Func(("[%s] Dbg: Buffering complete\n", pStream->szName)); 1656 fDoPlay = true; 1657 } 1658 /* Some audio files are shorter than the pre-buffering level (e.g. the "click" Explorer sounds on some Windows guests), 1659 * so make sure that we also play those by checking if the stream already is pending disable mode, even if we didn't 1660 * hit the pre-buffering watermark yet. 1661 * 1662 * To reproduce, use "Windows Navigation Start.wav" on Windows 7 (2824 samples). */ 1663 else if ( cFramesLive 1664 && pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE) 1665 { 1666 LogRel2(("Audio: Stream '%s' buffering complete (short sound)\n", pStream->szName)); 1667 Log3Func(("[%s] Dbg: Buffering complete (short)\n", pStream->szName)); 1668 fDoPlay = true; 1669 } 1670 1671 if (fDoPlay) 1672 { 1673 pStream->fThresholdReached = true; 1674 fJustStarted = true; 1675 LogRel2(("Audio: Stream '%s' started playing\n", pStream->szName)); 1676 Log3Func(("[%s] Dbg: started playing\n", pStream->szName)); 1677 } 1678 else /* Not yet, so still buffering audio data. */ 1679 LogRel2(("Audio: Stream '%s' is buffering (%RU8%% complete)\n", 1680 pStream->szName, (100 * cFramesLive) / pStream->Host.Cfg.Backend.cFramesPreBuffering)); 1681 } 1682 1683 if (fDoPlay) 1684 { 1685 uint32_t cfWritable = PDMAUDIOPCMPROPS_B2F(&pStream->Host.Cfg.Props, 1686 pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, 1687 pStream->pvBackend)); 1688 1689 uint32_t cfToPlay = 0; 1690 if (fJustStarted) 1691 cfToPlay = RT_MIN(cfWritable, cFramesPeriod); 1692 1693 if (!cfToPlay) 1694 { 1695 /* Did we reach/pass (in real time) the device scheduling slot? 1696 * Play as much as we can write to the backend then. */ 1697 if (cfPassedReal >= PDMAudioPropsMilliToFrames(&pStream->Host.Cfg.Props, 1698 pStream->Guest.Cfg.Device.cMsSchedulingHint)) 1699 cfToPlay = cfWritable; 1700 } 1701 1702 if (cfToPlay > cFramesLive) /* Don't try to play more than available. */ 1703 cfToPlay = cFramesLive; 1704 Log3Func(("[%s] Playing %RU32 frames (%RU64ms), now filled with %RU64ms -- %RU8%%\n", 1705 pStream->szName, cfToPlay, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cfToPlay), 1706 PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, AudioMixBufUsed(&pStream->Host.MixBuf)), 1707 AudioMixBufUsed(&pStream->Host.MixBuf) * 100 / AudioMixBufSize(&pStream->Host.MixBuf))); 1708 if (cfToPlay) 1709 { 1710 if (pThis->pHostDrvAudio->pfnStreamPlayBegin) 1711 pThis->pHostDrvAudio->pfnStreamPlayBegin(pThis->pHostDrvAudio, pStream->pvBackend); 1712 1713 /** @todo r=bird: I don't honestly see any difference in interleaved, 1714 * non-interrleaved, raw, complicate, or whatever frame format we're 1715 * dealing with here. We'll be formatting a chunk of audio data and feed 1716 * it to the backend, the formatting is taken care of by the mixer and 1717 * we don't really care about the format anywhere here. 1718 * 1719 * Raw audio is just stereo S64, btw. Since drvAudioStreamPlayRaw 1720 * actually copies the mixer data instead of accessing the internal mixer 1721 * buffer directly, there is no advantage to having separate code paths 1722 * here. It only leads to more incomplete crappy code (I find the code 1723 * quality quite appaling, given the amount of time spent on it). 1724 * 1725 * What's more, I think the non-interleaved designation here is wrong 1726 * anyway. Non-interleaved means a stereo chunk of 8 frames is 1727 * formatted: 1728 * - LLLLLLLLRRRRRRRR 1729 * whereas I'm pretty darn sure we do: 1730 * - LRLRLRLRLRLRLRLR 1731 * given that the mixer doesn't know how to output the former. See the 1732 * audioMixBufConvTo##a_Name##Stereo() code, it clearly output LR pairs. 1733 * 1734 * https://stackoverflow.com/questions/17879933/whats-the-interleaved-audio 1735 */ 1736 if (RT_LIKELY(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED)) 1737 rc = drvAudioStreamPlayNonInterleaved(pThis, pStream, cfToPlay, &cfPlayedTotal); 1738 else if (pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW) 1739 rc = drvAudioStreamPlayRaw(pThis, pStream, cfToPlay, &cfPlayedTotal); 1740 else 1741 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED); 1742 1743 if (pThis->pHostDrvAudio->pfnStreamPlayEnd) 1744 pThis->pHostDrvAudio->pfnStreamPlayEnd(pThis->pHostDrvAudio, pStream->pvBackend); 1745 1746 pStream->tsLastPlayedCapturedNs = RTTimeNanoTS(); 1747 } 1748 1749 Log3Func(("[%s] Dbg: fJustStarted=%RTbool, cfSched=%RU32 (%RU64ms), cfPassedReal=%RU32 (%RU64ms), " 1750 "cFramesLive=%RU32 (%RU64ms), cFramesPeriod=%RU32 (%RU64ms), cfWritable=%RU32 (%RU64ms), " 1751 "-> cfToPlay=%RU32 (%RU64ms), cfPlayed=%RU32 (%RU64ms)\n", 1752 pStream->szName, fJustStarted, 1753 PDMAudioPropsMilliToFrames(&pStream->Host.Cfg.Props, pStream->Guest.Cfg.Device.cMsSchedulingHint), 1754 pStream->Guest.Cfg.Device.cMsSchedulingHint, 1755 cfPassedReal, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cfPassedReal), 1756 cFramesLive, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesLive), 1757 cFramesPeriod, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesPeriod), 1758 cfWritable, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cfWritable), 1759 cfToPlay, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cfToPlay), 1760 cfPlayedTotal, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cfPlayedTotal))); 1761 } 1762 1763 if (RT_SUCCESS(rc)) 1764 { 1765 AudioMixBufFinish(&pStream->Host.MixBuf, cfPlayedTotal); 1766 1767 #ifdef VBOX_WITH_STATISTICS 1768 STAM_COUNTER_ADD (&pThis->Stats.TotalFramesOut, cfPlayedTotal); 1769 STAM_PROFILE_ADV_STOP(&pThis->Stats.DelayOut, out); 1770 1771 STAM_COUNTER_ADD (&pStream->Out.Stats.TotalFramesPlayed, cfPlayedTotal); 1772 STAM_COUNTER_INC (&pStream->Out.Stats.TotalTimesPlayed); 1773 #endif 1774 } 1775 1776 } while (0); 1777 1778 Log3Func(("[%s] End fStatus=%s, cFramesLive=%RU32, cfPlayedTotal=%RU32, rc=%Rrc\n", pStream->szName, 1779 dbgAudioStreamStatusToStr(szStreamSts, fStrmStatus), AudioMixBufLive(&pStream->Host.MixBuf), cfPlayedTotal, rc)); 1811 uint32_t cFramesPlayed = 0; 1812 rc = drvAudioStreamPlayLocked(pThis, pStream, &cFramesPlayed); 1780 1813 1781 1814 RTCritSectLeave(&pThis->CritSect); 1782 1815 1783 1816 if (RT_SUCCESS(rc) && pcFramesPlayed) 1784 *pcFramesPlayed = c fPlayedTotal;1817 *pcFramesPlayed = cFramesPlayed; 1785 1818 1786 1819 if (RT_FAILURE(rc)) -
trunk/src/VBox/Main/src-client/DrvAudioVRDE.cpp
r88253 r88255 507 507 static DECLCALLBACK(uint32_t) drvAudioVrdeHA_StreamGetWritable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream) 508 508 { 509 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio); 510 PVRDESTREAM pStreamVRDE = (PVRDESTREAM)pStream; 511 512 PPDMAUDIOPCMPROPS pProps = &pStreamVRDE->pCfg->Props; 513 514 RT_NOREF(pDrv, pProps); 515 516 /* Return frames instead of bytes here 517 * (since we specified PDMAUDIOSTREAMLAYOUT_RAW as the audio data layout). */ 509 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio); 510 RT_NOREF(pStream); 511 512 /** @todo Find some sane value here. We probably need a VRDE API VRDE to specify this. */ 518 513 if (pDrv->cClients) 519 return _16K; /** @todo Find some sane value here. We probably need a VRDE API VRDE to specify this. */ 520 514 return _16K * sizeof(PDMAUDIOFRAME); 521 515 return 0; 522 516 }
Note:
See TracChangeset
for help on using the changeset viewer.