VirtualBox

Changeset 88709 in vbox


Ignore:
Timestamp:
Apr 26, 2021 4:38:03 PM (4 years ago)
Author:
vboxsync
Message:

DrvAudio: Require PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF for output streams. bugref:9890

File:
1 edited

Legend:

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

    r88693 r88709  
    356356static void drvAudioStreamFree(PDRVAUDIOSTREAM pStream);
    357357static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx);
    358 static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, bool fWorkMixBuf);
     358static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx);
    359359static int drvAudioStreamPlayLocked(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t *pcFramesPlayed);
    360360static void drvAudioStreamDropInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx);
     
    12151215    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
    12161216    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
    1217     AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT,
    1218               ("Stream '%s' is not an output stream and therefore cannot be written to (direction is '%s')\n",
    1219                pStreamEx->Core.szName, PDMAudioDirGetName(pStreamEx->Core.enmDir)));
     1217    AssertMsgReturn(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT,
     1218                    ("Stream '%s' is not an output stream and therefore cannot be written to (direction is '%s')\n",
     1219                     pStreamEx->Core.szName, PDMAudioDirGetName(pStreamEx->Core.enmDir)), VERR_ACCESS_DENIED);
     1220    Assert(pStreamEx->fNoMixBufs);
    12201221
    12211222    AssertMsg(PDMAudioPropsIsSizeAligned(&pStreamEx->Guest.Cfg.Props, cbBuf),
    12221223              ("Stream '%s' got a non-frame-aligned write (%RU32 bytes)\n", pStreamEx->Core.szName, cbBuf));
    12231224
    1224     STAM_PROFILE_ADV_START(&pThis->Stats.DelayOut, out); /* (stopped in drvAudioStreamPlayLocked) */
     1225/// @todo    STAM_PROFILE_ADV_START(&pThis->Stats.DelayOut, out); /* (stopped in drvAudioStreamPlayLocked) */
    12251226
    12261227    int rc = RTCritSectEnter(&pThis->CritSect);
     
    12461247         * we're prebuffering.  There will be no pfnStreamPlay call in this mode.
    12471248         */
    1248         else if (pStreamEx->fNoMixBufs)
     1249        else
    12491250        {
    12501251            uint64_t offInternalBefore = pStreamEx->offInternal; RT_NOREF(offInternalBefore);
     
    12561257                AudioHlpFileWrite(pStreamEx->Out.Dbg.pFilePlayNonInterleaved, pvBuf, *pcbWritten, 0 /* fFlags */);
    12571258        }
    1258         /*
    1259          * Legacy mode:  Here we just dump the data in the guest side mixing buffer
    1260          * and then mixes it into the host side buffer.  Later the device code will
    1261          * make a pfnStreamPlay call which  recodes the data from the host side
    1262          * buffer and writes it to the host backend.
    1263          */
    1264         else
    1265         {
    1266             uint32_t cbWrittenTotal = 0;
    1267 
    1268             const uint32_t cbFree = AudioMixBufFreeBytes(&pStreamEx->Host.MixBuf);
    1269             if (cbFree < cbBuf)
    1270                 LogRel2(("Audio: Lost audio output (%RU64ms, %RU32 free but needs %RU32) due to full host stream buffer '%s'\n",
    1271                          PDMAudioPropsBytesToMilli(&pStreamEx->Host.Cfg.Props, cbBuf - cbFree), cbFree, cbBuf, pStreamEx->Core.szName));
    1272 
    1273             uint32_t cbToWrite = RT_MIN(cbBuf, cbFree);
    1274             if (cbToWrite)
    1275             {
    1276                 /* We use the guest side mixing buffer as an intermediate buffer to do some
    1277                  * (first) processing (if needed), so always write the incoming data at offset 0. */
    1278                 uint32_t cFramesGstWritten = 0;
    1279                 rc = AudioMixBufWriteAt(&pStreamEx->Guest.MixBuf, 0 /* offFrames */, pvBuf, cbToWrite, &cFramesGstWritten);
    1280                 if (RT_SUCCESS(rc) && cFramesGstWritten > 0)
    1281                 {
    1282                     if (pThis->Out.Cfg.Dbg.fEnabled)
    1283                         AudioHlpFileWrite(pStreamEx->Out.Dbg.pFileStreamWrite, pvBuf, cbToWrite, 0 /* fFlags */);
    1284 
    1285                     uint32_t cFramesGstMixed = 0;
    1286                     if (cFramesGstWritten)
    1287                     {
    1288                         int rc2 = AudioMixBufMixToParentEx(&pStreamEx->Guest.MixBuf, 0 /* cSrcOffset */,
    1289                                                            cFramesGstWritten /* cSrcFrames */, &cFramesGstMixed /* pcSrcMixed */);
    1290                         if (RT_SUCCESS(rc2))
    1291                         {
    1292                             const uint64_t tsNowNs = RTTimeNanoTS();
    1293 
    1294                             Log3Func(("[%s] Writing %RU32 frames (%RU64ms)\n",
    1295                                       pStreamEx->Core.szName, cFramesGstWritten, PDMAudioPropsFramesToMilli(&pStreamEx->Guest.Cfg.Props, cFramesGstWritten)));
    1296 
    1297                             Log3Func(("[%s] Last written %RU64ns (%RU64ms), now filled with %RU64ms -- %RU8%%\n",
    1298                                       pStreamEx->Core.szName, tsNowNs - pStreamEx->nsLastReadWritten,
    1299                                       (tsNowNs - pStreamEx->nsLastReadWritten) / RT_NS_1MS,
    1300                                       PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, AudioMixBufUsed(&pStreamEx->Host.MixBuf)),
    1301                                       AudioMixBufUsed(&pStreamEx->Host.MixBuf) * 100 / AudioMixBufSize(&pStreamEx->Host.MixBuf)));
    1302 
    1303                             pStreamEx->nsLastReadWritten = tsNowNs;
    1304                             /* Keep going. */
    1305                         }
    1306                         else
    1307                         {
    1308                             AssertMsgFailed(("[%s] Mixing failed: cbToWrite=%RU32, cfWritten=%RU32, cfMixed=%RU32, rc=%Rrc\n",
    1309                                              pStreamEx->Core.szName, cbToWrite, cFramesGstWritten, cFramesGstMixed, rc2));
    1310                             if (RT_SUCCESS(rc))
    1311                                 rc = rc2;
    1312                         }
    1313 
    1314                         cbWrittenTotal = AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cFramesGstWritten);
    1315 
    1316                         STAM_COUNTER_ADD(&pThis->Stats.TotalFramesWritten,  cFramesGstWritten);
    1317                         STAM_COUNTER_ADD(&pThis->Stats.TotalFramesMixedOut, cFramesGstMixed);
    1318                         Assert(cFramesGstWritten >= cFramesGstMixed);
    1319                         STAM_COUNTER_ADD(&pThis->Stats.TotalFramesLostOut,  cFramesGstWritten - cFramesGstMixed);
    1320                         STAM_COUNTER_ADD(&pThis->Stats.TotalBytesWritten,   cbWrittenTotal);
    1321 
    1322                         STAM_COUNTER_ADD(&pStreamEx->Out.Stats.TotalFramesWritten, cFramesGstWritten);
    1323                         STAM_COUNTER_INC(&pStreamEx->Out.Stats.TotalTimesWritten);
    1324                     }
    1325 
    1326                     Log3Func(("[%s] Dbg: cbBuf=%RU32, cbToWrite=%RU32, cfHstUsed=%RU32, cfHstfLive=%RU32, cFramesGstWritten=%RU32, "
    1327                               "cFramesGstMixed=%RU32, cbWrittenTotal=%RU32, rc=%Rrc\n",
    1328                               pStreamEx->Core.szName, cbBuf, cbToWrite, AudioMixBufUsed(&pStreamEx->Host.MixBuf),
    1329                               AudioMixBufLive(&pStreamEx->Host.MixBuf), cFramesGstWritten, cFramesGstMixed, cbWrittenTotal, rc));
    1330                 }
    1331                 else
    1332                     AssertMsgFailed(("[%s] Write failed: cbToWrite=%RU32, cFramesGstWritten=%RU32, rc=%Rrc\n",
    1333                                      pStreamEx->Core.szName, cbToWrite, cFramesGstWritten, rc));
    1334             }
    1335             else
    1336                 rc = VERR_BUFFER_OVERFLOW;
    1337             *pcbWritten = cbWrittenTotal;
    1338             pStreamEx->offInternal += cbWrittenTotal;
    1339         }
    13401259    }
    13411260    else
     
    13971316    AssertRCReturn(rc, rc);
    13981317
    1399     rc = drvAudioStreamIterateInternal(pThis, pStreamEx, false /*fWorkMixBuf*/); /** @todo r=bird: why didn't it work the mixing buffer initially.  We can probably set this to true...  It may cause repeat work though. */
     1318    rc = drvAudioStreamIterateInternal(pThis, pStreamEx);
    14001319
    14011320    RTCritSectLeave(&pThis->CritSect);
     
    14881407 * @param   pThis       Pointer to driver instance.
    14891408 * @param   pStreamEx   Stream to iterate.
    1490  * @param   fWorkMixBuf Push data from the mixing buffer to the backend.
     1409 *
    14911410 * @todo    r=bird: Don't know why the default behavior isn't to push data into
    14921411 *          the backend...  We'll never get out of the pending-disable state if
    14931412 *          the mixing buffer doesn't empty out.
    14941413 */
    1495 static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, bool fWorkMixBuf)
     1414static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx)
    14961415{
    14971416    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     
    15391458         *        should probably not be here at all. */
    15401459        uint32_t cFramesLive;
    1541         if (pStreamEx->fNoMixBufs)
    1542         {
    1543             cFramesLive = pStreamEx->Out.cbPreBuffered;
    1544             if (cFramesLive > 0)
    1545             {
    1546                 uint32_t cbIgnored = 0;
    1547                 drvAudioStreamWriteNoMixBufs(pThis, pStreamEx, NULL, 0, &cbIgnored);
    1548                 cFramesLive = PDMAudioPropsBytesToFrames(&pStreamEx->Core.Props, pStreamEx->Out.cbPreBuffered);
    1549             }
    1550         }
    1551         else
    1552         {
    1553             cFramesLive = AudioMixBufLive(&pStreamEx->Host.MixBuf);
    1554             if (cFramesLive > 0 && fWorkMixBuf)
    1555             {
    1556                 uint32_t cIgnored = 0;
    1557                 drvAudioStreamPlayLocked(pThis, pStreamEx, &cIgnored);
    1558 
    1559                 cFramesLive = AudioMixBufLive(&pStreamEx->Host.MixBuf);
    1560             }
     1460        cFramesLive = pStreamEx->Out.cbPreBuffered;
     1461        if (cFramesLive > 0)
     1462        {
     1463            uint32_t cbIgnored = 0;
     1464            drvAudioStreamWriteNoMixBufs(pThis, pStreamEx, NULL, 0, &cbIgnored);
     1465            cFramesLive = PDMAudioPropsBytesToFrames(&pStreamEx->Core.Props, pStreamEx->Out.cbPreBuffered);
    15611466        }
    15621467        Log3Func(("[%s] cFramesLive=%RU32\n", pStreamEx->Core.szName, cFramesLive));
     
    16341539            if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE)
    16351540            {
    1636                 drvAudioStreamIterateInternal(pThis, pStreamEx, true /*fWorkMixBuf*/);
     1541                drvAudioStreamIterateInternal(pThis, pStreamEx);
    16371542
    16381543                if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE)
     
    16561561}
    16571562
    1658 /**
    1659  * Worker for drvAudioStreamPlay that does the actual playing.
    1660  *
    1661  * @returns VBox status code.
    1662  * @param   pThis           The audio driver instance data.
    1663  * @param   pStreamEx       The stream to play.
    1664  * @param   cFramesToPlay   Number of audio frames to play.  The backend is
    1665  *                          supposed to have buffer space for this.
    1666  * @param   pcFramesPlayed  Where to return the number of audio frames played.
    1667  */
    1668 static int drvAudioStreamPlayDoIt(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t cFramesToPlay, uint32_t *pcFramesPlayed)
    1669 {
    1670     Assert(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT);
    1671 
    1672     /*
    1673      * Push data to the host device.
    1674      */
    1675     int      rc          = VINF_SUCCESS;
    1676     uint32_t cFramesLeft = cFramesToPlay;
    1677     while (cFramesLeft > 0)
    1678     {
    1679         /*
    1680          * Grab a chunk of audio data in the backend format.
    1681          */
    1682         uint8_t  abChunk[_4K];
    1683         uint32_t cFramesRead = 0;
    1684         rc = AudioMixBufAcquireReadBlock(&pStreamEx->Host.MixBuf, abChunk,
    1685                                          RT_MIN(sizeof(abChunk), AUDIOMIXBUF_F2B(&pStreamEx->Host.MixBuf, cFramesLeft)),
    1686                                          &cFramesRead);
    1687         AssertRCBreak(rc);
    1688 
    1689         uint32_t cbRead = AUDIOMIXBUF_F2B(&pStreamEx->Host.MixBuf, cFramesRead);
    1690         Assert(cbRead <= sizeof(abChunk));
    1691 
    1692         /*
    1693          * Feed it to the backend.
    1694          */
    1695         uint32_t cFramesPlayed = 0;
    1696         uint32_t cbPlayed      = 0;
    1697         rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStreamEx->pBackend, abChunk, cbRead, &cbPlayed);
    1698         if (RT_SUCCESS(rc))
    1699         {
    1700             if (pThis->Out.Cfg.Dbg.fEnabled)
    1701                 AudioHlpFileWrite(pStreamEx->Out.Dbg.pFilePlayNonInterleaved, abChunk, cbPlayed, 0 /* fFlags */);
    1702 
    1703             if (cbRead != cbPlayed)
    1704                 LogRel2(("Audio: Host stream '%s' played wrong amount (%RU32 bytes read but played %RU32)\n",
    1705                          pStreamEx->Core.szName, cbRead, cbPlayed));
    1706 
    1707             cFramesPlayed  = AUDIOMIXBUF_B2F(&pStreamEx->Host.MixBuf, cbPlayed);
    1708             AssertStmt(cFramesLeft >= cFramesPlayed, cFramesPlayed = cFramesLeft);
    1709             cFramesLeft   -= cFramesPlayed;
    1710         }
    1711 
    1712         AudioMixBufReleaseReadBlock(&pStreamEx->Host.MixBuf, cFramesPlayed);
    1713 
    1714         AssertRCBreak(rc); /* (this is here for Acquire/Release symmetry - which isn't at all necessary) */
    1715         AssertBreak(cbPlayed > 0); /* (ditto) */
    1716     }
    1717 
    1718     Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStreamEx->Core.szName, cFramesToPlay - cFramesLeft, cFramesToPlay, rc));
    1719     *pcFramesPlayed = cFramesToPlay - cFramesLeft;
    1720     return rc;
    1721 }
    1722 
    1723 /**
    1724  * Worker for drvAudioStreamPlay.
    1725  */
    1726 static int drvAudioStreamPlayLocked(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t *pcFramesPlayed)
    1727 {
    1728     /*
    1729      * Zero the frame count so we can return at will.
    1730      */
    1731     *pcFramesPlayed = 0;
    1732 
    1733     PDMAUDIOSTREAMSTS fStrmStatus = pStreamEx->Core.fStatus;
    1734 #ifdef LOG_ENABLED
    1735     char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
    1736 #endif
    1737     Log3Func(("[%s] Start fStatus=%s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, fStrmStatus)));
    1738 
    1739     /*
    1740      * Operational?
    1741      */
    1742     if (pThis->pHostDrvAudio)
    1743     { /* likely? */ }
    1744     else
    1745         return VERR_PDM_NO_ATTACHED_DRIVER;
    1746 
    1747     if (   pThis->Out.fEnabled
    1748         && PDMAudioStrmStatusIsReady(fStrmStatus))
    1749     { /* likely? */ }
    1750     else
    1751         return VERR_AUDIO_STREAM_NOT_READY;
    1752 
    1753     /*
    1754      * Get number of frames in the mix buffer and do some logging.
    1755      */
    1756     uint32_t const cFramesLive = AudioMixBufLive(&pStreamEx->Host.MixBuf);
    1757     Log3Func(("[%s] Last played %'RI64 ns ago; filled with %u frm / %RU64 ms / %RU8%% total%s\n",
    1758               pStreamEx->Core.szName, pStreamEx->fThresholdReached ? RTTimeNanoTS() - pStreamEx->nsLastPlayedCaptured : -1, cFramesLive,
    1759               PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesLive),
    1760               (100 * cFramesLive) / AudioMixBufSize(&pStreamEx->Host.MixBuf), pStreamEx->fThresholdReached ? "" : ", pre-buffering"));
    1761 
    1762     /*
    1763      * Restart pre-buffering if we're having a buffer-underrun.
    1764      */
    1765     if (   cFramesLive != 0              /* no underrun */
    1766         || !pStreamEx->fThresholdReached /* or still pre-buffering. */)
    1767     { /* likely */ }
    1768     else
    1769     {
    1770         /* It's not an underrun if the host audio driver still has an reasonable amount
    1771            buffered.  We don't have a direct way of querying that, so instead we'll use
    1772            some heuristics based on number of writable bytes now compared to when
    1773            prebuffering ended the first time around. */
    1774         uint32_t cbBuffered = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStreamEx->pBackend);
    1775         if (cbBuffered < pStreamEx->Out.cbBackendMaxWritable)
    1776             cbBuffered = pStreamEx->Out.cbBackendMaxWritable - cbBuffered;
    1777         else
    1778             cbBuffered = 0;
    1779         uint32_t cbMinBuf = PDMAudioPropsMilliToBytes(&pStreamEx->Host.Cfg.Props, pStreamEx->Guest.Cfg.Device.cMsSchedulingHint * 2);
    1780         Log3Func(("Potential underrun: cbBuffered=%#x vs cbMinBuf=%#x\n", cbBuffered, cbMinBuf));
    1781         if (cbBuffered < cbMinBuf)
    1782         {
    1783             LogRel2(("Audio: Buffer underrun for stream '%s' (%RI64 ms since last call, %u buffered)\n",
    1784                      pStreamEx->Core.szName, RTTimeNanoTS() - pStreamEx->nsLastPlayedCaptured, cbBuffered));
    1785 
    1786             /* Re-enter the pre-buffering stage again if enabled. */
    1787             if (pStreamEx->Host.Cfg.Backend.cFramesPreBuffering > 0)
    1788             {
    1789                 pStreamEx->fThresholdReached = false;
    1790                 STAM_REL_COUNTER_INC(&pThis->Out.StatsReBuffering);
    1791             }
    1792         }
    1793     }
    1794 
    1795     /*
    1796      * Work the pre-buffering.
    1797      *
    1798      * This is straight forward, the backend
    1799      */
    1800     uint32_t cbWritable;
    1801     bool fJustStarted = false;
    1802     if (pStreamEx->fThresholdReached)
    1803     {
    1804         /* not-prebuffering, likely after a while at least */
    1805         cbWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStreamEx->pBackend);
    1806     }
    1807     else
    1808     {
    1809         /*
    1810          * Did we reach the backend's playback (pre-buffering) threshold?
    1811          * Can be 0 if no pre-buffering desired.
    1812          */
    1813         if (cFramesLive >= pStreamEx->Host.Cfg.Backend.cFramesPreBuffering)
    1814         {
    1815             LogRel2(("Audio: Stream '%s' buffering complete!\n", pStreamEx->Core.szName));
    1816             pStreamEx->fThresholdReached = fJustStarted = true;
    1817         }
    1818         /*
    1819          * Some audio files are shorter than the pre-buffering level (e.g. the
    1820          * "click" Explorer sounds on some Windows guests), so make sure that we
    1821          * also play those by checking if the stream already is pending disable
    1822          * mode, even if we didn't hit the pre-buffering watermark yet.
    1823          *
    1824          * Try play "Windows Navigation Start.wav" on Windows 7 (2824 samples).
    1825          */
    1826         else if (   cFramesLive > 0
    1827                  && (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE))
    1828         {
    1829             LogRel2(("Audio: Stream '%s' buffering complete (short sound)!\n", pStreamEx->Core.szName));
    1830             pStreamEx->fThresholdReached = fJustStarted = true;
    1831         }
    1832         /*
    1833          * Not yet, so still buffering audio data.
    1834          */
    1835         else
    1836         {
    1837             LogRel2(("Audio: Stream '%s' is buffering (%RU8%% complete)...\n",
    1838                      pStreamEx->Core.szName, (100 * cFramesLive) / pStreamEx->Host.Cfg.Backend.cFramesPreBuffering));
    1839             return VINF_SUCCESS;
    1840         }
    1841 
    1842         /* Hack alert! This is for the underrun detection.  */
    1843         cbWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStreamEx->pBackend);
    1844         if (cbWritable > pStreamEx->Out.cbBackendMaxWritable)
    1845             pStreamEx->Out.cbBackendMaxWritable = cbWritable;
    1846     }
    1847     pStreamEx->Out.Stats.cbBackendWritableBefore = cbWritable;
    1848 
    1849     /*
    1850      * Figure out how much to play now.
    1851      * Easy, as much as the host audio backend will allow us to.
    1852      */
    1853     uint32_t cFramesWritable = PDMAUDIOPCMPROPS_B2F(&pStreamEx->Host.Cfg.Props, cbWritable);
    1854     uint32_t cFramesToPlay   = cFramesWritable;
    1855     if (cFramesToPlay > cFramesLive) /* Don't try to play more than available, we don't want to block. */
    1856         cFramesToPlay = cFramesLive;
    1857 
    1858     Log3Func(("[%s] Playing %RU32 frames (%RU64 ms), now filled with %RU64 ms -- %RU8%%\n",
    1859               pStreamEx->Core.szName, cFramesToPlay, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesToPlay),
    1860               PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, AudioMixBufUsed(&pStreamEx->Host.MixBuf)),
    1861               AudioMixBufUsed(&pStreamEx->Host.MixBuf) * 100 / AudioMixBufSize(&pStreamEx->Host.MixBuf)));
    1862 
    1863     /*
    1864      * Do the playing if we decided to play something.
    1865      */
    1866     int rc;
    1867     if (cFramesToPlay)
    1868     {
    1869         rc = drvAudioStreamPlayDoIt(pThis, pStreamEx, cFramesToPlay, pcFramesPlayed);
    1870 
    1871         pStreamEx->nsLastPlayedCaptured = RTTimeNanoTS();
    1872         pStreamEx->Out.Stats.cbBackendWritableAfter = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio,
    1873                                                                                                  pStreamEx->pBackend);
    1874     }
    1875     else
    1876         rc = VINF_SUCCESS;
    1877 
    1878     Log3Func(("[%s] 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",
    1879               pStreamEx->Core.szName,
    1880               cFramesLive, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesLive),
    1881               pStreamEx->Host.Cfg.Backend.cFramesPeriod,
    1882               PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, pStreamEx->Host.Cfg.Backend.cFramesPeriod),
    1883               cFramesWritable, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesWritable),
    1884               cFramesToPlay, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesToPlay),
    1885               *pcFramesPlayed, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, *pcFramesPlayed),
    1886               fJustStarted ? "just-started" : ""));
    1887     RT_NOREF(fJustStarted);
    1888 
    1889     if (RT_SUCCESS(rc))
    1890     {
    1891         AudioMixBufFinish(&pStreamEx->Host.MixBuf, *pcFramesPlayed);
    1892 
    1893         STAM_PROFILE_ADV_STOP(&pThis->Stats.DelayOut, out);
    1894         STAM_COUNTER_ADD(&pThis->Stats.TotalFramesOut, *pcFramesPlayed);
    1895         STAM_COUNTER_ADD(&pStreamEx->Out.Stats.TotalFramesPlayed, *pcFramesPlayed);
    1896         STAM_COUNTER_INC(&pStreamEx->Out.Stats.TotalTimesPlayed);
    1897     }
    1898     return rc;
    1899 }
    1900 
    19011563
    19021564/**
     
    19051567static DECLCALLBACK(int) drvAudioStreamPlay(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream, uint32_t *pcFramesPlayed)
    19061568{
    1907     PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
    1908     AssertPtr(pThis);
    1909     PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
    1910     AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER);
    1911     AssertPtrNullReturn(pcFramesPlayed, VERR_INVALID_POINTER);
    1912     AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
    1913     AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
    1914     AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT,
    1915               ("Stream '%s' is not an output stream and therefore cannot be played back (direction is 0x%x)\n",
    1916                pStreamEx->Core.szName, pStreamEx->Core.enmDir));
    1917     AssertReturn(!pStreamEx->fNoMixBufs, VERR_INVALID_FUNCTION);
    1918 
    1919     int rc = RTCritSectEnter(&pThis->CritSect);
    1920     AssertRCReturn(rc, rc);
    1921 
    1922     uint32_t cFramesPlayed = 0;
    1923     rc = drvAudioStreamPlayLocked(pThis, pStreamEx, &cFramesPlayed);
    1924 
    1925     RTCritSectLeave(&pThis->CritSect);
    1926 
    1927     if (RT_SUCCESS(rc) && pcFramesPlayed)
    1928         *pcFramesPlayed = cFramesPlayed;
    1929 
    1930     if (RT_FAILURE(rc))
    1931         LogFlowFunc(("[%s] Failed with %Rrc\n", pStreamEx->Core.szName, rc));
    1932     return rc;
    1933 }
     1569    RT_NOREF(pInterface, pStream, pcFramesPlayed);
     1570    AssertFailed(/* OBSOLETE! */);
     1571    return VERR_NOT_SUPPORTED;
     1572}
     1573
    19341574
    19351575/**
     
    28452485    if (!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF))
    28462486    {
     2487        Assert(pCfgHost->enmDir == PDMAUDIODIR_IN);
    28472488        rc = AudioMixBufInit(&pStreamEx->Host.MixBuf, pStreamEx->Core.szName, &CfgHostAcq.Props, CfgHostAcq.Backend.cFramesBufferSize);
    28482489        AssertRCReturn(rc, rc);
     
    28782519    if (!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF))
    28792520    {
     2521        Assert(pCfgHost->enmDir == PDMAUDIODIR_IN);
    28802522        rc = AudioMixBufInit(&pStreamEx->Guest.MixBuf, pStreamEx->Core.szName, &pCfgGuest->Props, CfgHostAcq.Backend.cFramesBufferSize);
    28812523        AssertRCReturn(rc, rc);
     
    28872529    if (!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF))
    28882530    {
    2889         if (pCfgGuest->enmDir == PDMAUDIODIR_IN)
    2890         {
    2891             /* Host (Parent) -> Guest (Child). */
    2892             rc = AudioMixBufLinkTo(&pStreamEx->Host.MixBuf, &pStreamEx->Guest.MixBuf);
    2893             AssertRC(rc);
    2894         }
    2895         else
    2896         {
    2897             /* Guest (Parent) -> Host (Child). */
    2898             rc = AudioMixBufLinkTo(&pStreamEx->Guest.MixBuf, &pStreamEx->Host.MixBuf);
    2899             AssertRC(rc);
    2900         }
     2531        Assert(pCfgHost->enmDir == PDMAUDIODIR_IN);
     2532        /* Host (Parent) -> Guest (Child). */
     2533        rc = AudioMixBufLinkTo(&pStreamEx->Host.MixBuf, &pStreamEx->Guest.MixBuf);
     2534        AssertRC(rc);
    29012535    }
    29022536
     
    29102544    if (!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF))
    29112545    {
     2546        Assert(pCfgHost->enmDir == PDMAUDIODIR_IN);
    29122547        PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Host.MixBuf.cFrames, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
    29132548                               "Host side: The size of the mixer buffer (in frames)",   "%s/1-HostMixBufSize", pStreamEx->Core.szName);
    29142549        PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Guest.MixBuf.cFrames, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
    29152550                               "Guest side: The size of the mixer buffer (in frames)",  "%s/2-GuestMixBufSize", pStreamEx->Core.szName);
    2916         if (pCfgGuest->enmDir == PDMAUDIODIR_IN)
    2917         {
    2918             PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Host.MixBuf.cMixed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
    2919                                    "Host side: Number of frames in the mixer buffer",   "%s/1-HostMixBufUsed", pStreamEx->Core.szName);
    2920             PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Guest.MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
    2921                                    "Guest side: Number of frames in the mixer buffer",  "%s/2-GuestMixBufUsed", pStreamEx->Core.szName);
    2922         }
    2923         else
    2924         {
    2925             PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Host.MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
    2926                                    "Host side: Number of frames in the mixer buffer",     "%s/1-HostMixBufUsed", pStreamEx->Core.szName);
    2927             PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Guest.MixBuf.cMixed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
    2928                                    "Guest side: Number of frames in the mixer buffer",    "%s/2-GuestMixBufUsed", pStreamEx->Core.szName);
    2929         }
     2551        PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Host.MixBuf.cMixed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
     2552                               "Host side: Number of frames in the mixer buffer",   "%s/1-HostMixBufUsed", pStreamEx->Core.szName);
     2553        PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Guest.MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
     2554                               "Guest side: Number of frames in the mixer buffer",  "%s/2-GuestMixBufUsed", pStreamEx->Core.szName);
    29302555    }
    29312556    if (pCfgGuest->enmDir == PDMAUDIODIR_IN)
     
    29962621    AssertReturn(pCfgHost->enmDir == pCfgGuest->enmDir, VERR_MISMATCH);
    29972622    AssertReturn(pCfgHost->enmDir == PDMAUDIODIR_IN || pCfgHost->enmDir == PDMAUDIODIR_OUT, VERR_NOT_SUPPORTED);
     2623    /* Require PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF for output streams: */
     2624    AssertReturn((fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF) || pCfgHost->enmDir == PDMAUDIODIR_IN, VERR_INVALID_FLAGS);
    29982625
    29992626    /*
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette