VirtualBox

Changeset 88511 in vbox


Ignore:
Timestamp:
Apr 14, 2021 6:56:49 PM (4 years ago)
Author:
vboxsync
Message:

DrvHostAudioPulseAudio: Went over the buffer and output/input code. bugref:9890

File:
1 edited

Legend:

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

    r88500 r88511  
    143143    /** Pulse playback and buffer metrics. */
    144144    pa_buffer_attr         BufAttr;
    145     /** Pointer to Pulse sample peeking buffer. */
    146     const uint8_t         *pu8PeekBuf;
    147     /** Current size (in bytes) of peeking data in
    148      *  buffer. */
     145    /** Input: Pointer to Pulse sample peek buffer. */
     146    const uint8_t         *pbPeekBuf;
     147    /** Input: Current size (in bytes) of peeked data in buffer. */
    149148    size_t                 cbPeekBuf;
    150     /** Our offset (in bytes) in peeking buffer. */
     149    /** Input: Our offset (in bytes) in peek data buffer. */
    151150    size_t                 offPeekBuf;
    152     /** Asynchronous drain operation.  This is used as an indicator of whether
    153      *  we're currently draining the stream (will be cleaned up before
     151    /** Output: Asynchronous drain operation.  This is used as an indicator of
     152     *  whether we're currently draining the stream (will be cleaned up before
    154153     *  resume/re-enable). */
    155154    pa_operation          *pDrainOp;
     
    162161     * won't do any after-freed accesses.) */
    163162    pa_operation          *pTriggerOp;
    164     /** Current latency (in us). */
     163    /** Output: Current latency (in microsecs). */
    165164    uint64_t               cUsLatency;
    166165#ifdef LOG_ENABLED
    167     /** Start time stamp (in us) of stream playback / recording. */
     166    /** Creation timestamp (in microsecs) of stream playback / recording. */
    168167    pa_usec_t              tsStartUs;
    169     /** Time stamp (in us) when last read from / written to the stream. */
     168    /** Timestamp (in microsecs) when last read from / written to the stream. */
    170169    pa_usec_t              tsLastReadWrittenUs;
    171170#endif
     
    10381037    pStreamPA->pDrv                = pThis;
    10391038    pStreamPA->pDrainOp            = NULL;
    1040     pStreamPA->pu8PeekBuf          = NULL;
     1039    pStreamPA->pbPeekBuf          = NULL;
    10411040    pStreamPA->SampleSpec.rate     = PDMAudioPropsHz(&pCfgReq->Props);
    10421041    pStreamPA->SampleSpec.channels = PDMAudioPropsChannels(&pCfgReq->Props);
     
    12631262    if (pStreamPA->Cfg.enmDir == PDMAUDIODIR_OUT)
    12641263    {
    1265         /* Output - Ignore request if we've got a drain running, it will cork it
    1266                      when it completes. */
    12671264        if (pStreamPA->pDrainOp)
    12681265        {
     
    12801277     * For input stream we always cork it, but we clean up the peek buffer first.
    12811278     */
    1282     else if (pStreamPA->pu8PeekBuf) /** @todo Do we need to drop the peek buffer?*/
    1283     {
     1279    /** @todo r=bird: It is (probably) not technically be correct to drop the peek buffer
     1280     *        here when we're only pausing the stream (VM paused) as it means we'll
     1281     *        risk underruns when later resuming. */
     1282    else if (pStreamPA->pbPeekBuf) /** @todo Do we need to drop the peek buffer?*/
     1283    {
     1284        pStreamPA->pbPeekBuf  = NULL;
     1285        pStreamPA->cbPeekBuf  = 0;
    12841286        pa_stream_drop(pStreamPA->pStream);
    1285         pStreamPA->pu8PeekBuf = NULL;
    12861287    }
    12871288
     
    14741475
    14751476
    1476 static uint32_t drvHostAudioPaStreamGetAvailable(PDRVHOSTPULSEAUDIO pThis, PPULSEAUDIOSTREAM pStreamPA)
    1477 {
    1478     pa_threaded_mainloop_lock(pThis->pMainLoop);
    1479 
    1480     uint32_t cbAvail = 0;
    1481 
    1482     if (PA_STREAM_IS_GOOD(pa_stream_get_state(pStreamPA->pStream)))
    1483     {
    1484         if (pStreamPA->Cfg.enmDir == PDMAUDIODIR_IN)
    1485         {
    1486             cbAvail = (uint32_t)pa_stream_readable_size(pStreamPA->pStream);
    1487             Log3Func(("cbReadable=%RU32\n", cbAvail));
    1488         }
    1489         else if (pStreamPA->Cfg.enmDir == PDMAUDIODIR_OUT)
    1490         {
    1491             size_t cbWritable = pa_stream_writable_size(pStreamPA->pStream);
    1492 
    1493             Log3Func(("cbWritable=%zu, maxLength=%RU32, minReq=%RU32\n",
    1494                       cbWritable, pStreamPA->BufAttr.maxlength, pStreamPA->BufAttr.minreq));
    1495 
    1496             /* Don't report more writable than the PA server can handle. */
    1497             if (cbWritable > pStreamPA->BufAttr.maxlength)
    1498                 cbWritable = pStreamPA->BufAttr.maxlength;
    1499 
    1500             cbAvail = (uint32_t)cbWritable;
     1477/**
     1478 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetReadable}
     1479 */
     1480static DECLCALLBACK(uint32_t) drvHostAudioPaHA_StreamGetReadable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     1481{
     1482    PDRVHOSTPULSEAUDIO  pThis      = RT_FROM_MEMBER(pInterface, DRVHOSTPULSEAUDIO, IHostAudio);
     1483    PPULSEAUDIOSTREAM   pStreamPA  = (PPULSEAUDIOSTREAM)pStream;
     1484    uint32_t            cbReadable = 0;
     1485    if (pStreamPA->Cfg.enmDir == PDMAUDIODIR_IN)
     1486    {
     1487        pa_threaded_mainloop_lock(pThis->pMainLoop);
     1488
     1489        pa_stream_state_t const enmState = pa_stream_get_state(pStreamPA->pStream);
     1490        if (PA_STREAM_IS_GOOD(enmState))
     1491        {
     1492            size_t cbReadablePa = pa_stream_readable_size(pStreamPA->pStream);
     1493            if (cbReadablePa != (size_t)-1)
     1494                cbReadable = (uint32_t)cbReadablePa;
     1495            else
     1496                drvHostAudioPaError(pThis, "pa_stream_readable_size failed on '%s'", pStreamPA->Cfg.szName);
    15011497        }
    15021498        else
    1503             AssertFailed();
    1504     }
    1505 
    1506     pa_threaded_mainloop_unlock(pThis->pMainLoop);
    1507 
    1508     return cbAvail;
    1509 }
    1510 
    1511 
    1512 /**
    1513  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetReadable}
    1514  */
    1515 static DECLCALLBACK(uint32_t) drvHostAudioPaHA_StreamGetReadable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
    1516 {
    1517     return drvHostAudioPaStreamGetAvailable(RT_FROM_MEMBER(pInterface, DRVHOSTPULSEAUDIO, IHostAudio),
    1518                                             (PPULSEAUDIOSTREAM)pStream);
     1499            LogFunc(("non-good stream state: %d\n", enmState));
     1500
     1501        pa_threaded_mainloop_unlock(pThis->pMainLoop);
     1502    }
     1503    Log3Func(("returns %#x (%u)\n", cbReadable, cbReadable));
     1504    return cbReadable;
    15191505}
    15201506
     
    15251511static DECLCALLBACK(uint32_t) drvHostAudioPaHA_StreamGetWritable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
    15261512{
    1527     return drvHostAudioPaStreamGetAvailable(RT_FROM_MEMBER(pInterface, DRVHOSTPULSEAUDIO, IHostAudio),
    1528                                             (PPULSEAUDIOSTREAM)pStream);
     1513    PDRVHOSTPULSEAUDIO  pThis      = RT_FROM_MEMBER(pInterface, DRVHOSTPULSEAUDIO, IHostAudio);
     1514    PPULSEAUDIOSTREAM   pStreamPA  = (PPULSEAUDIOSTREAM)pStream;
     1515    uint32_t            cbWritable = 0;
     1516    if (pStreamPA->Cfg.enmDir == PDMAUDIODIR_OUT)
     1517    {
     1518        pa_threaded_mainloop_lock(pThis->pMainLoop);
     1519
     1520        pa_stream_state_t const enmState = pa_stream_get_state(pStreamPA->pStream);
     1521        if (PA_STREAM_IS_GOOD(enmState))
     1522        {
     1523            size_t cbWritablePa = pa_stream_writable_size(pStreamPA->pStream);
     1524            if (cbWritablePa != (size_t)-1)
     1525            {
     1526                /* Don't report more writable than the PA server can handle. */
     1527                if (cbWritablePa <= pStreamPA->BufAttr.maxlength)
     1528                    cbWritable = (uint32_t)cbWritablePa;
     1529                else
     1530                {
     1531                    Log3Func(("Clamping cbWritablePa=%#zx to maxLength=%#RX32\n", cbWritablePa, pStreamPA->BufAttr.maxlength));
     1532                    cbWritable = (uint32_t)pStreamPA->BufAttr.maxlength;
     1533                }
     1534            }
     1535            else
     1536                drvHostAudioPaError(pThis, "pa_stream_writable_size failed on '%s'", pStreamPA->Cfg.szName);
     1537        }
     1538        else
     1539            LogFunc(("non-good stream state: %d\n", enmState));
     1540
     1541        pa_threaded_mainloop_unlock(pThis->pMainLoop);
     1542    }
     1543    Log3Func(("returns %#x (%u) [max=%#RX32 min=%#RX32]\n",
     1544              cbWritable, cbWritable, pStreamPA->BufAttr.maxlength, pStreamPA->BufAttr.minreq));
     1545    return cbWritable;
    15291546}
    15301547
     
    15391556
    15401557    /* Check PulseAudio's general status. */
    1541     PDMAUDIOSTREAMSTS fStrmSts = PDMAUDIOSTREAMSTS_FLAGS_NONE;
    1542     if (   pThis->pContext
    1543         && PA_CONTEXT_IS_GOOD(pa_context_get_state(pThis->pContext)))
    1544        fStrmSts = PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED | PDMAUDIOSTREAMSTS_FLAGS_ENABLED;
    1545 
    1546     return fStrmSts;
     1558    if (pThis->pContext)
     1559    {
     1560        pa_context_state_t const enmState = pa_context_get_state(pThis->pContext);
     1561        if (PA_CONTEXT_IS_GOOD(enmState))
     1562        {
     1563            /** @todo should we check the actual stream state? */
     1564            return PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED | PDMAUDIOSTREAMSTS_FLAGS_ENABLED;
     1565        }
     1566        LogFunc(("non-good context state: %d\n", enmState));
     1567    }
     1568    else
     1569        LogFunc(("No context!\n"));
     1570    return PDMAUDIOSTREAMSTS_FLAGS_NONE;
    15471571}
    15481572
     
    15641588
    15651589#ifdef LOG_ENABLED
    1566     const pa_usec_t tsNowUs         = pa_rtclock_now();
    1567     const pa_usec_t tsDeltaPlayedUs = tsNowUs - pStreamPA->tsLastReadWrittenUs;
    1568     pStreamPA->tsLastReadWrittenUs  = tsNowUs;
    1569     Log3Func(("tsDeltaPlayedMs=%RU64\n", tsDeltaPlayedUs / RT_US_1MS));
     1590    const pa_usec_t tsNowUs = pa_rtclock_now();
     1591    Log3Func(("play delta: %RU64 us; cbBuf=%#x\n", tsNowUs - pStreamPA->tsLastReadWrittenUs, cbBuf));
     1592    pStreamPA->tsLastReadWrittenUs = tsNowUs;
    15701593#endif
    15711594
    1572     int          rc;
    1573     size_t const cbWriteable = pa_stream_writable_size(pStreamPA->pStream);
    1574     if (cbWriteable != (size_t)-1)
    1575     {
    1576         size_t cbLeft = RT_MIN(cbWriteable, cbBuf);
    1577         Assert(cbLeft > 0 /* At this point we better have *something* to write (DrvAudio checked before calling). */);
    1578         if (pa_stream_write(pStreamPA->pStream, pvBuf, cbLeft, NULL /*pfnFree*/, 0 /*offset*/, PA_SEEK_RELATIVE) >= 0)
    1579         {
    1580             *pcbWritten = (uint32_t)cbLeft;
    1581             rc = VINF_SUCCESS;
     1595    /*
     1596     * Using a loop here so we can take maxlength into account when writing.
     1597     */
     1598    int      rc             = VINF_SUCCESS;
     1599    uint32_t cbTotalWritten = 0;
     1600    uint32_t iLoop;
     1601    for (iLoop = 0; ; iLoop++)
     1602    {
     1603        size_t const cbWriteable = pa_stream_writable_size(pStreamPA->pStream);
     1604        if (   cbWriteable != (size_t)-1
     1605            && cbWriteable >= PDMAudioPropsFrameSize(&pStreamPA->Cfg.Props))
     1606        {
     1607            uint32_t cbToWrite = (uint32_t)RT_MIN(RT_MIN(cbWriteable, pStreamPA->BufAttr.maxlength), cbBuf);
     1608            cbToWrite = PDMAudioPropsFloorBytesToFrame(&pStreamPA->Cfg.Props, cbToWrite);
     1609            if (pa_stream_write(pStreamPA->pStream, pvBuf, cbToWrite, NULL /*pfnFree*/, 0 /*offset*/, PA_SEEK_RELATIVE) >= 0)
     1610            {
     1611                cbTotalWritten += cbToWrite;
     1612                cbBuf          -= cbToWrite;
     1613                if (!cbBuf)
     1614                    break;
     1615                pvBuf = (uint8_t const *)pvBuf + cbToWrite;
     1616                Log3Func(("%#x left to write\n", cbBuf));
     1617            }
     1618            else
     1619            {
     1620                rc = drvHostAudioPaError(pStreamPA->pDrv, "Failed to write to output stream");
     1621                break;
     1622            }
    15821623        }
    15831624        else
    1584             rc = drvHostAudioPaError(pStreamPA->pDrv, "Failed to write to output stream");
    1585     }
     1625        {
     1626            if (cbWriteable == (size_t)-1)
     1627                rc = drvHostAudioPaError(pStreamPA->pDrv, "pa_stream_writable_size failed on '%s'", pStreamPA->Cfg.szName);
     1628            break;
     1629        }
     1630    }
     1631
     1632    pa_threaded_mainloop_unlock(pThis->pMainLoop);
     1633
     1634    *pcbWritten = cbTotalWritten;
     1635    if (RT_SUCCESS(rc) || cbTotalWritten == 0)
     1636    { /* likely */ }
    15861637    else
    1587         rc = drvHostAudioPaError(pStreamPA->pDrv, "Failed to determine output data size");
    1588 
    1589     pa_threaded_mainloop_unlock(pThis->pMainLoop);
     1638    {
     1639        LogFunc(("Supressing %Rrc because we wrote %#x bytes\n", rc, cbTotalWritten));
     1640        rc = VINF_SUCCESS;
     1641    }
     1642    Log3Func(("returns %Rrc *pcbWritten=%#x iLoop=%u\n", rc, cbTotalWritten, iLoop));
    15901643    return rc;
    15911644}
     
    16051658    AssertPtrReturn(pcbRead, VERR_INVALID_POINTER);
    16061659
    1607     /* We should only call pa_stream_readable_size() once and trust the first value. */
     1660#ifdef LOG_ENABLED
     1661    const pa_usec_t tsNowUs = pa_rtclock_now();
     1662    Log3Func(("capture delta: %RU64 us; cbBuf=%#x\n", tsNowUs - pStreamPA->tsLastReadWrittenUs, cbBuf));
     1663    pStreamPA->tsLastReadWrittenUs = tsNowUs;
     1664#endif
     1665
     1666    /*
     1667     * If we have left over peek buffer space from the last call,
     1668     * copy out the data from there.
     1669     */
     1670    uint32_t cbTotalRead = 0;
     1671    if (   pStreamPA->pbPeekBuf
     1672        && pStreamPA->offPeekBuf < pStreamPA->cbPeekBuf)
     1673    {
     1674        uint32_t cbToCopy = pStreamPA->cbPeekBuf - pStreamPA->offPeekBuf;
     1675        if (cbToCopy >= cbBuf)
     1676        {
     1677            memcpy(pvBuf, &pStreamPA->pbPeekBuf[pStreamPA->offPeekBuf], cbBuf);
     1678            pStreamPA->offPeekBuf += cbBuf;
     1679            *pcbRead               = cbBuf;
     1680            if (cbToCopy == cbBuf)
     1681            {
     1682                pa_threaded_mainloop_lock(pThis->pMainLoop);
     1683                pStreamPA->pbPeekBuf  = NULL;
     1684                pStreamPA->cbPeekBuf  = 0;
     1685                pa_stream_drop(pStreamPA->pStream);
     1686                pa_threaded_mainloop_unlock(pThis->pMainLoop);
     1687            }
     1688            Log3Func(("returns *pcbRead=%#x from prev peek buf (%#x/%#x)\n", cbBuf, pStreamPA->offPeekBuf, pStreamPA->cbPeekBuf));
     1689            return VINF_SUCCESS;
     1690        }
     1691
     1692        memcpy(pvBuf, &pStreamPA->pbPeekBuf[pStreamPA->offPeekBuf], cbToCopy);
     1693        cbBuf       -= cbToCopy;
     1694        pvBuf        = (uint8_t *)pvBuf + cbToCopy;
     1695        cbTotalRead += cbToCopy;
     1696        pStreamPA->offPeekBuf = pStreamPA->cbPeekBuf;
     1697    }
     1698
     1699    /*
     1700     * Copy out what we can.
     1701     */
     1702    int rc = VINF_SUCCESS;
    16081703    pa_threaded_mainloop_lock(pThis->pMainLoop);
    1609     size_t cbAvail = pa_stream_readable_size(pStreamPA->pStream);
    1610     pa_threaded_mainloop_unlock(pThis->pMainLoop);
    1611 
    1612     if (cbAvail == (size_t)-1)
    1613         return drvHostAudioPaError(pStreamPA->pDrv, "Failed to determine input data size");
    1614 
    1615     /* If the buffer was not dropped last call, add what remains. */
    1616     if (pStreamPA->pu8PeekBuf)
    1617     {
    1618         Assert(pStreamPA->cbPeekBuf >= pStreamPA->offPeekBuf);
    1619         cbAvail += (pStreamPA->cbPeekBuf - pStreamPA->offPeekBuf);
    1620     }
    1621 
    1622     Log3Func(("cbAvail=%zu\n", cbAvail));
    1623 
    1624     if (!cbAvail) /* No data? Bail out. */
    1625     {
    1626         *pcbRead = 0;
    1627         return VINF_SUCCESS;
    1628     }
    1629 
    1630     int rc = VINF_SUCCESS;
    1631 
    1632     size_t cbToRead = RT_MIN(cbAvail, cbBuf);
    1633 
    1634     Log3Func(("cbToRead=%zu, cbAvail=%zu, offPeekBuf=%zu, cbPeekBuf=%zu\n",
    1635               cbToRead, cbAvail, pStreamPA->offPeekBuf, pStreamPA->cbPeekBuf));
    1636 
    1637     uint32_t cbReadTotal = 0;
    1638 
    1639     while (cbToRead)
    1640     {
    1641         /* If there is no data, do another peek. */
    1642         if (!pStreamPA->pu8PeekBuf)
    1643         {
    1644             pa_threaded_mainloop_lock(pThis->pMainLoop);
    1645             pa_stream_peek(pStreamPA->pStream,
    1646                            (const void**)&pStreamPA->pu8PeekBuf, &pStreamPA->cbPeekBuf);
    1647             pa_threaded_mainloop_unlock(pThis->pMainLoop);
    1648 
    1649             pStreamPA->offPeekBuf = 0;
    1650 
    1651             /* No data anymore?
    1652              * Note: If there's a data hole (cbPeekBuf then contains the length of the hole)
    1653              *       we need to drop the stream lateron. */
    1654             if (   !pStreamPA->pu8PeekBuf
    1655                 && !pStreamPA->cbPeekBuf)
     1704    while (cbBuf > 0)
     1705    {
     1706        /*
     1707         * Drop the old peek buffer first, if we have one.
     1708         */
     1709        if (pStreamPA->pbPeekBuf)
     1710        {
     1711            Assert(pStreamPA->offPeekBuf >= pStreamPA->cbPeekBuf);
     1712            pStreamPA->pbPeekBuf  = NULL;
     1713            pStreamPA->cbPeekBuf  = 0;
     1714            pa_stream_drop(pStreamPA->pStream);
     1715        }
     1716
     1717        /*
     1718         * Check if there is anything to read, the get the peek buffer for it.
     1719         */
     1720        size_t cbAvail = pa_stream_readable_size(pStreamPA->pStream);
     1721        if (cbAvail > 0 && cbAvail != (size_t)-1)
     1722        {
     1723            pStreamPA->pbPeekBuf  = NULL;
     1724            pStreamPA->cbPeekBuf  = 0;
     1725            int rcPa = pa_stream_peek(pStreamPA->pStream, (const void **)&pStreamPA->pbPeekBuf, &pStreamPA->cbPeekBuf);
     1726            if (rcPa == 0)
    16561727            {
     1728                if (pStreamPA->cbPeekBuf)
     1729                {
     1730                    if (pStreamPA->pbPeekBuf)
     1731                    {
     1732                        /*
     1733                         * We got data back. Copy it into the return buffer, return if it's full.
     1734                         */
     1735                        if (cbBuf < pStreamPA->cbPeekBuf)
     1736                        {
     1737                            memcpy(pvBuf, pStreamPA->pbPeekBuf, cbBuf);
     1738                            cbTotalRead          += cbBuf;
     1739                            pStreamPA->offPeekBuf = cbBuf;
     1740                            cbBuf = 0;
     1741                            break;
     1742                        }
     1743                        memcpy(pvBuf, pStreamPA->pbPeekBuf, pStreamPA->cbPeekBuf);
     1744                        cbBuf       -= pStreamPA->cbPeekBuf;
     1745                        pvBuf        = (uint8_t *)pvBuf + pStreamPA->cbPeekBuf;
     1746                        cbTotalRead += pStreamPA->cbPeekBuf;
     1747
     1748                        pStreamPA->pbPeekBuf = NULL;
     1749                    }
     1750                    else
     1751                    {
     1752                        /*
     1753                         * We got a hole (drop needed). We will skip it as we leave it to
     1754                         * the device's DMA engine to fill in buffer gaps with silence.
     1755                         */
     1756                        LogFunc(("pa_stream_peek returned a %#zx (%zu) byte hole - skipping.\n",
     1757                                 pStreamPA->cbPeekBuf, pStreamPA->cbPeekBuf));
     1758                    }
     1759                    pStreamPA->cbPeekBuf = 0;
     1760                    pa_stream_drop(pStreamPA->pStream);
     1761                }
     1762                else
     1763                {
     1764                    Assert(!pStreamPA->pbPeekBuf);
     1765                    LogFunc(("pa_stream_peek returned empty buffer\n"));
     1766                    break;
     1767                }
     1768            }
     1769            else
     1770            {
     1771                rc = drvHostAudioPaError(pStreamPA->pDrv, "pa_stream_peek failed on '%s' (%d)", pStreamPA->Cfg.szName, rcPa);
     1772                pStreamPA->pbPeekBuf  = NULL;
     1773                pStreamPA->cbPeekBuf  = 0;
    16571774                break;
    16581775            }
    16591776        }
    1660 
    1661         Assert(pStreamPA->cbPeekBuf >= pStreamPA->offPeekBuf);
    1662         size_t cbToWrite = RT_MIN(pStreamPA->cbPeekBuf - pStreamPA->offPeekBuf, cbToRead);
    1663 
    1664         Log3Func(("cbToRead=%zu, cbToWrite=%zu, offPeekBuf=%zu, cbPeekBuf=%zu, pu8PeekBuf=%p\n",
    1665                   cbToRead, cbToWrite,
    1666                   pStreamPA->offPeekBuf, pStreamPA->cbPeekBuf, pStreamPA->pu8PeekBuf));
    1667 
    1668         if (   cbToWrite
    1669             /* Only copy data if it's not a data hole (see above). */
    1670             && pStreamPA->pu8PeekBuf
    1671             && pStreamPA->cbPeekBuf)
    1672         {
    1673             memcpy((uint8_t *)pvBuf + cbReadTotal, pStreamPA->pu8PeekBuf + pStreamPA->offPeekBuf, cbToWrite);
    1674 
    1675             Assert(cbToRead >= cbToWrite);
    1676             cbToRead          -= cbToWrite;
    1677             cbReadTotal       += cbToWrite;
    1678 
    1679             pStreamPA->offPeekBuf += cbToWrite;
    1680             Assert(pStreamPA->offPeekBuf <= pStreamPA->cbPeekBuf);
    1681         }
    1682 
    1683         if (/* Nothing to write anymore? Drop the buffer. */
    1684                !cbToWrite
    1685             /* Was there a hole in the peeking buffer? Drop it. */
    1686             || !pStreamPA->pu8PeekBuf
    1687             /* If the buffer is done, drop it. */
    1688             || pStreamPA->offPeekBuf == pStreamPA->cbPeekBuf)
    1689         {
    1690             pa_threaded_mainloop_lock(pThis->pMainLoop);
    1691             pa_stream_drop(pStreamPA->pStream);
    1692             pa_threaded_mainloop_unlock(pThis->pMainLoop);
    1693 
    1694             pStreamPA->pu8PeekBuf = NULL;
    1695         }
    1696     }
    1697 
    1698     if (RT_SUCCESS(rc))
    1699         *pcbRead = cbReadTotal;
     1777        else
     1778        {
     1779            if (cbAvail != (size_t)-1)
     1780                rc = drvHostAudioPaError(pStreamPA->pDrv, "pa_stream_readable_size failed on '%s'", pStreamPA->Cfg.szName);
     1781            break;
     1782        }
     1783    }
     1784    pa_threaded_mainloop_unlock(pThis->pMainLoop);
     1785
     1786    *pcbRead = cbTotalRead;
     1787    if (RT_SUCCESS(rc) || cbTotalRead == 0)
     1788    { /* likely */ }
     1789    else
     1790    {
     1791        LogFunc(("Supressing %Rrc because we're returning %#x bytes\n", rc, cbTotalRead));
     1792        rc = VINF_SUCCESS;
     1793    }
     1794    Log3Func(("returns %Rrc *pcbRead=%#x (%#x left, peek %#x/%#x)\n",
     1795              rc, cbTotalRead, cbBuf, pStreamPA->offPeekBuf, pStreamPA->cbPeekBuf));
    17001796    return rc;
    17011797}
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