VirtualBox

Changeset 88255 in vbox


Ignore:
Timestamp:
Mar 23, 2021 8:43:58 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
143458
Message:

DrvAudio,DrvAudioVRDE: Refactoring drvAudioStreamPlay (no actual change, just different code structure). bugref:9890

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/pdmaudioifs.h

    r88253 r88255  
    17701770     * Returns the amount which is writable to the audio (output) stream.
    17711771     *
    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.
    17741773     * @param   pInterface          Pointer to the interface structure containing the called function pointer.
    17751774     * @param   pStream             Pointer to audio stream.
  • trunk/src/VBox/Devices/Audio/DrvAudio.cpp

    r88253 r88255  
    15821582
    15831583/**
     1584 * Worker for drvAudioStreamPlay.
     1585 */
     1586static 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/**
    15841796 * @interface_method_impl{PDMIAUDIOCONNECTOR,pfnStreamPlay}
    15851797 */
     
    15931805              ("Stream '%s' is not an output stream and therefore cannot be played back (direction is 0x%x)\n",
    15941806               pStream->szName, pStream->enmDir));
     1807
    15951808    int rc = RTCritSectEnter(&pThis->CritSect);
    15961809    AssertRCReturn(rc, rc);
    15971810
    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);
    17801813
    17811814    RTCritSectLeave(&pThis->CritSect);
    17821815
    17831816    if (RT_SUCCESS(rc) && pcFramesPlayed)
    1784         *pcFramesPlayed = cfPlayedTotal;
     1817        *pcFramesPlayed = cFramesPlayed;
    17851818
    17861819    if (RT_FAILURE(rc))
  • trunk/src/VBox/Main/src-client/DrvAudioVRDE.cpp

    r88253 r88255  
    507507static DECLCALLBACK(uint32_t) drvAudioVrdeHA_StreamGetWritable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
    508508{
    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. */
    518513    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);
    521515    return 0;
    522516}
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