VirtualBox

Changeset 88282 in vbox for trunk/src/VBox/Devices/Audio


Ignore:
Timestamp:
Mar 24, 2021 6:57:14 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
143493
Message:

Audio: Cleaned up the alsa and pulse audio play methods. Two doxygen fixes. bugref:9890

Location:
trunk/src/VBox/Devices/Audio
Files:
3 edited

Legend:

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

    r88277 r88282  
    650650 *
    651651 * @returns Pointer to matching conversion function, NULL if not supported.
    652  * @param   pProp       The audio format to find a "from" converter for.
     652 * @param   pProps  The audio format to find a "from" converter for.
    653653 */
    654654static PFNPDMAUDIOMIXBUFCONVFROM audioMixBufConvFromLookup(PCPDMAUDIOPCMPROPS pProps)
     
    713713 *
    714714 * @returns Pointer to matching conversion function, NULL if not supported.
    715  * @param   pProp       The audio format to find a "to" converter for.
     715 * @param   pProps  The audio format to find a "to" converter for.
    716716 */
    717717static PFNPDMAUDIOMIXBUFCONVTO audioMixBufConvToLookup(PCPDMAUDIOPCMPROPS pProps)
  • trunk/src/VBox/Devices/Audio/DrvHostAudioAlsa.cpp

    r88269 r88282  
    8585    /** Pointer to allocated ALSA PCM configuration to use. */
    8686    snd_pcm_t          *phPCM;
    87     /** Scratch buffer. */
     87    /** Scratch buffer.
     88     * @todo r=bird: WHY THE *BEEEEP* DO WE NEED THIS? Do I have to go search svn
     89     *       history for this (probably just an 'updates' commit)? */
    8890    void               *pvBuf;
    8991    /** Size (in bytes) of allocated scratch buffer. */
     
    735737 */
    736738static DECLCALLBACK(int) drvHostAlsaAudioHA_StreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
    737                                                        const void *pvBuf, uint32_t uBufSize, uint32_t *puWritten)
     739                                                       const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
    738740{
    739741    PALSAAUDIOSTREAM pStreamALSA = (PALSAAUDIOSTREAM)pStream;
    740742    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    741     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    742     AssertPtrReturn(pvBuf,      VERR_INVALID_POINTER);
    743     AssertReturn(uBufSize,        VERR_INVALID_PARAMETER);
    744     /* puWritten is optional. */
    745     Log4Func(("pvBuf=%p uBufSize=%#x (%u) state=%s - %s\n", pvBuf, uBufSize, uBufSize,
     743    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     744    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
     745    AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
     746    AssertPtrReturn(pcbWritten, VERR_INVALID_POINTER);
     747    Log4Func(("pvBuf=%p uBufSize=%#x (%u) state=%s - %s\n", pvBuf, cbBuf, cbBuf,
    746748              snd_pcm_state_name(snd_pcm_state(pStreamALSA->phPCM)), pStreamALSA->pCfg->szName));
    747749
    748     PPDMAUDIOSTREAMCFG pCfg = pStreamALSA->pCfg;
    749     AssertPtr(pCfg);
    750 
    751     int rc;
    752 
    753     uint32_t cbWrittenTotal = 0;
    754 
    755     do
    756     {
    757         snd_pcm_sframes_t csAvail;
    758         rc = alsaStreamGetAvail(pStreamALSA->phPCM, &csAvail);
    759         if (RT_FAILURE(rc))
    760         {
    761             LogFunc(("Error getting number of playback frames, rc=%Rrc\n", rc));
    762             break;
    763         }
    764 
    765         if (!csAvail)
    766             break;
    767 
    768         size_t cbToWrite = RT_MIN((unsigned)PDMAUDIOSTREAMCFG_F2B(pCfg, csAvail), pStreamALSA->cbBuf);
    769         if (!cbToWrite)
    770             break;
    771 
    772         /* Do not write more than available. */
    773         if (cbToWrite > uBufSize)
    774             cbToWrite = uBufSize;
    775 
    776         memcpy(pStreamALSA->pvBuf, pvBuf, cbToWrite);
    777 
    778         snd_pcm_sframes_t csWritten = 0;
    779 
    780         /* Don't try infinitely on recoverable errors. */
    781         unsigned iTry;
    782         for (iTry = 0; iTry < ALSA_RECOVERY_TRIES_MAX; iTry++)
    783         {
    784             csWritten = snd_pcm_writei(pStreamALSA->phPCM, pStreamALSA->pvBuf,
    785                                        PDMAUDIOSTREAMCFG_B2F(pCfg, cbToWrite));
    786             Log4Func(("snd_pcm_writei w/ cbToWrite=%u -> %ld (frames) [csAvail=%ld]\n", cbToWrite, csWritten, csAvail));
    787             if (csWritten <= 0)
     750    /*
     751     * Determine how much we can write (caller actually did this
     752     * already, but we repeat it just to be sure or something).
     753     */
     754    snd_pcm_sframes_t cFramesAvail;
     755    int rc = alsaStreamGetAvail(pStreamALSA->phPCM, &cFramesAvail);
     756    if (RT_SUCCESS(rc))
     757    {
     758        Assert(cFramesAvail);
     759        if (cFramesAvail)
     760        {
     761            PCPDMAUDIOPCMPROPS pProps    = &pStreamALSA->pCfg->Props;
     762            uint32_t           cbToWrite = PDMAudioPropsFramesToBytes(pProps, (uint32_t)cFramesAvail);
     763            cbToWrite = RT_MIN(cbToWrite, (uint32_t)pStreamALSA->cbBuf);
     764            if (cbToWrite)
    788765            {
    789                 switch (csWritten)
     766                if (cbToWrite > cbBuf)
     767                    cbToWrite = cbBuf;
     768
     769                /*
     770                 * Now we copy the stuff into our scratch buffer for some
     771                 * totally unexplained reason.
     772                 */
     773                memcpy(pStreamALSA->pvBuf, pvBuf, cbToWrite);
     774
     775                /*
     776                 * Try write the data.
     777                 */
     778                uint32_t cFramesToWrite = PDMAudioPropsBytesToFrames(pProps, cbToWrite);
     779                snd_pcm_sframes_t cFramesWritten = snd_pcm_writei(pStreamALSA->phPCM, pStreamALSA->pvBuf, cFramesToWrite);
     780                if (cFramesWritten > 0)
    790781                {
    791                     case 0:
     782                    Log4Func(("snd_pcm_writei w/ cbToWrite=%u -> %ld (frames) [cFramesAvail=%ld]\n",
     783                              cbToWrite, cFramesWritten, cFramesAvail));
     784                    *pcbWritten = PDMAudioPropsFramesToBytes(pProps, cFramesWritten);
     785                    return VINF_SUCCESS;
     786                }
     787                LogFunc(("snd_pcm_writei w/ cbToWrite=%u -> %ld [cFramesAvail=%ld]\n", cbToWrite, cFramesWritten, cFramesAvail));
     788
     789
     790                /*
     791                 * There are a couple of error we can recover from, try to do so.
     792                 * Only don't try too many times.
     793                 */
     794                for (unsigned iTry = 0;
     795                     (cFramesWritten == -EPIPE || cFramesWritten == -ESTRPIPE) && iTry < ALSA_RECOVERY_TRIES_MAX;
     796                     iTry++)
     797                {
     798                    if (cFramesWritten == -EPIPE)
    792799                    {
    793                         LogFunc(("Failed to write %zu bytes\n", cbToWrite));
    794                         rc = VERR_ACCESS_DENIED;
    795                         break;
     800                        /* underrun occurred */
     801                        rc = alsaStreamRecover(pStreamALSA->phPCM);
     802                        if (RT_SUCCESS(rc))
     803                            LogFlowFunc(("Recovered from playback (iTry=%u)\n", iTry));
     804                        else
     805                            break;
    796806                    }
    797 
    798                     case -EPIPE:
     807                    else
    799808                    {
    800                         rc = alsaStreamRecover(pStreamALSA->phPCM);
    801                         if (RT_FAILURE(rc))
    802                             break;
    803 
    804                         LogFlowFunc(("Recovered from playback\n"));
    805                         continue;
    806                     }
    807 
    808                     case -ESTRPIPE:
    809                     {
    810                         /* Stream was suspended and waiting for a recovery. */
     809                        /* an suspended event occurred, needs resuming. */
    811810                        rc = alsaStreamResume(pStreamALSA->phPCM);
    812                         if (RT_FAILURE(rc))
     811                        if (RT_SUCCESS(rc))
     812                            LogFlowFunc(("Resumed suspended output stream (iTry=%u)\n", iTry));
     813                        else
    813814                        {
    814                             LogRel(("ALSA: Failed to resume output stream\n"));
     815                            LogRel(("ALSA: Failed to resume output stream (iTry=%u, rc=%Rrc)\n", iTry, rc));
    815816                            break;
    816817                        }
    817 
    818                         LogFlowFunc(("Resumed suspended output stream\n"));
    819                         continue;
    820818                    }
    821819
    822                     default:
    823                         LogFlowFunc(("Failed to write %RU32 bytes, error unknown\n", cbToWrite));
    824                         rc = VERR_GENERAL_FAILURE; /** @todo */
    825                         break;
     820                    cFramesWritten = snd_pcm_writei(pStreamALSA->phPCM, pStreamALSA->pvBuf, cFramesToWrite);
     821                    if (cFramesWritten > 0)
     822                    {
     823                        Log4Func(("snd_pcm_writei w/ cbToWrite=%u -> %ld (frames) [cFramesAvail=%ld]\n",
     824                                  cbToWrite, cFramesWritten, cFramesAvail));
     825                        *pcbWritten = PDMAudioPropsFramesToBytes(pProps, cFramesWritten);
     826                        return VINF_SUCCESS;
     827                    }
     828                    LogFunc(("snd_pcm_writei w/ cbToWrite=%u -> %ld [cFramesAvail=%ld, iTry=%d]\n", cbToWrite, cFramesWritten, cFramesAvail, iTry));
     829                } /* For number of tries. */
     830
     831                /* Make sure we return with an error. */
     832                if (RT_SUCCESS_NP(rc))
     833                {
     834                    if (cFramesWritten == 0)
     835                        rc = VERR_ACCESS_DENIED;
     836                    else
     837                    {
     838                        rc = RTErrConvertFromErrno(-cFramesWritten);
     839                        LogFunc(("Failed to write %RU32 bytes: %ld (%Rrc)\n", cbToWrite, cFramesWritten, rc));
     840                    }
    826841                }
    827842            }
    828             else
    829                 break;
    830         } /* For number of tries. */
    831 
    832         if (   iTry == ALSA_RECOVERY_TRIES_MAX
    833             && csWritten <= 0)
    834             rc = VERR_BROKEN_PIPE;
    835 
    836         if (RT_FAILURE(rc))
    837             break;
    838 
    839         cbWrittenTotal = PDMAUDIOSTREAMCFG_F2B(pCfg, csWritten);
    840 
    841     } while (0);
    842 
    843     if (RT_SUCCESS(rc))
    844     {
    845         if (puWritten)
    846             *puWritten = cbWrittenTotal;
    847     }
    848 
     843        }
     844    }
     845    else
     846        LogFunc(("Error getting number of playback frames, rc=%Rrc\n", rc));
     847    *pcbWritten = 0;
    849848    return rc;
    850849}
  • trunk/src/VBox/Devices/Audio/DrvHostAudioPulseAudio.cpp

    r88269 r88282  
    991991 */
    992992static DECLCALLBACK(int) drvHostPulseAudioHA_StreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
    993                                                         const void *pvBuf, uint32_t uBufSize, uint32_t *puWritten)
    994 {
    995     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    996     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    997     AssertPtrReturn(pvBuf,      VERR_INVALID_POINTER);
    998     AssertReturn(uBufSize,         VERR_INVALID_PARAMETER);
    999     /* puWritten is optional. */
    1000 
    1001     PDRVHOSTPULSEAUDIO pThis     = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
    1002     PPULSEAUDIOSTREAM  pPAStream = (PPULSEAUDIOSTREAM)pStream;
    1003 
    1004     int rc = VINF_SUCCESS;
    1005 
    1006     uint32_t cbWrittenTotal = 0;
     993                                                        const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
     994{
     995    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
     996    AssertPtr(pThis);
     997    PPULSEAUDIOSTREAM pPAStream = (PPULSEAUDIOSTREAM)pStream;
     998    AssertPtrReturn(pPAStream, VERR_INVALID_POINTER);
     999    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
     1000    AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
     1001    AssertPtrReturn(pcbWritten, VERR_INVALID_POINTER);
    10071002
    10081003    pa_threaded_mainloop_lock(pThis->pMainLoop);
     
    10111006    const pa_usec_t tsNowUs         = pa_rtclock_now();
    10121007    const pa_usec_t tsDeltaPlayedUs = tsNowUs - pPAStream->tsLastReadWrittenUs;
    1013 
    1014     Log3Func(("tsDeltaPlayedMs=%RU64\n", tsDeltaPlayedUs / 1000 /* ms */));
    1015 
    10161008    pPAStream->tsLastReadWrittenUs  = tsNowUs;
     1009    Log3Func(("tsDeltaPlayedMs=%RU64\n", tsDeltaPlayedUs / RT_US_1MS));
    10171010#endif
    10181011
    1019     do
    1020     {
    1021         size_t cbWriteable = pa_stream_writable_size(pPAStream->pStream);
    1022         if (cbWriteable == (size_t)-1)
    1023         {
    1024             rc = paError(pPAStream->pDrv, "Failed to determine output data size");
    1025             break;
    1026         }
    1027 
    1028         size_t cbLeft = RT_MIN(cbWriteable, uBufSize);
    1029         Assert(cbLeft); /* At this point we better have *something* to write. */
    1030 
    1031         while (cbLeft)
    1032         {
    1033             uint32_t cbChunk = cbLeft; /* Write all at once for now. */
    1034 
    1035             if (pa_stream_write(pPAStream->pStream, (uint8_t *)pvBuf + cbWrittenTotal, cbChunk, NULL /* Cleanup callback */,
    1036                                 0, PA_SEEK_RELATIVE) < 0)
    1037             {
    1038                 rc = paError(pPAStream->pDrv, "Failed to write to output stream");
    1039                 break;
    1040             }
    1041 
    1042             Assert(cbLeft  >= cbChunk);
    1043             cbLeft         -= cbChunk;
    1044             cbWrittenTotal += cbChunk;
    1045         }
    1046 
    1047     } while (0);
     1012    int          rc;
     1013    size_t const cbWriteable = pa_stream_writable_size(pPAStream->pStream);
     1014    if (cbWriteable != (size_t)-1)
     1015    {
     1016        size_t cbLeft = RT_MIN(cbWriteable, cbBuf);
     1017        Assert(cbLeft > 0 /* At this point we better have *something* to write (DrvAudio checked before calling). */);
     1018        if (pa_stream_write(pPAStream->pStream, pvBuf, cbLeft, NULL /*pfnFree*/, 0 /*offset*/, PA_SEEK_RELATIVE) >= 0)
     1019        {
     1020            *pcbWritten = (uint32_t)cbLeft;
     1021            rc = VINF_SUCCESS;
     1022        }
     1023        else
     1024            rc = paError(pPAStream->pDrv, "Failed to write to output stream");
     1025    }
     1026    else
     1027        rc = paError(pPAStream->pDrv, "Failed to determine output data size");
    10481028
    10491029    pa_threaded_mainloop_unlock(pThis->pMainLoop);
    1050 
    1051     if (RT_SUCCESS(rc))
    1052     {
    1053         if (puWritten)
    1054             *puWritten = cbWrittenTotal;
    1055     }
    1056 
    10571030    return rc;
    10581031}
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