VirtualBox

Changeset 89450 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jun 1, 2021 11:55:53 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
144804
Message:

DrvHostAudioAlsa: Simplify the drvHostAlsaAudioHA_StreamCreate stuff, do the same config for both input and output. Started preparing to get rid of ALSAAUDIOSTREAMCFG. bugref:9890

File:
1 edited

Legend:

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

    r89449 r89450  
    9393    unsigned long       period_size;
    9494    /** For playback:  Starting to play threshold (in audio frames).
    95      *  For Capturing: Starting to capture threshold (in audio frames). */
     95     *  For Capturing: ~~Starting to capture threshold (in audio frames)~~ !nothing! */
    9696    unsigned long       threshold;
    9797
     
    404404{
    405405    AssertReturn(cChannels > 0, VERR_INVALID_PARAMETER);
    406     AssertReturn(cChannels < 16, VERR_INVALID_PARAMETER);
     406    AssertReturn(cChannels < PDMAUDIO_MAX_CHANNELS, VERR_INVALID_PARAMETER);
    407407    switch (fmt)
    408408    {
     
    458458 *
    459459 * @returns 0 on success, negative errno on failure.
    460  * @param   hPCM               ALSA stream to set software parameters for.
    461  * @param   fIn                 Whether this is an input stream or not.
    462  * @param   pCfgReq             Requested configuration to set.
    463  * @param   pCfgObt             Obtained configuration on success. Might differ from requested configuration.
    464  */
    465 static int alsaStreamSetSWParams(snd_pcm_t *hPCM, bool fIn, PALSAAUDIOSTREAMCFG pCfgReq, PALSAAUDIOSTREAMCFG pCfgObt)
     460 * @param   hPCM            ALSA stream to set software parameters for.
     461 * @param   fIn             Whether this is an input stream or not.
     462 * @param   pAlsaCfgReq     Requested configuration to set (ALSA).
     463 * @param   pAlsaCfgObt     Obtained configuration on success (ALSA).
     464 *                          Might differ from requested configuration.
     465 */
     466static int alsaStreamSetSWParams(snd_pcm_t *hPCM, bool fIn, PALSAAUDIOSTREAMCFG pAlsaCfgReq, PALSAAUDIOSTREAMCFG pAlsaCfgObt)
    466467{
    467468    if (fIn) /* For input streams there's nothing to do in here right now. */
     
    479480       one continuous chunk when we should start playing.  But since it is
    480481       configurable, we'll set a reasonable minimum of two DMA periods or
    481        max 64 milliseconds (the pCfgReq->threshold value).
     482       max 64 milliseconds (the pAlsaCfgReq->threshold value).
    482483
    483484       Of course we also have to make sure the threshold is below the buffer
    484485       size, or ALSA will never start playing. */
    485     unsigned long cFramesThreshold = RT_MIN(pCfgObt->period_size * 2, pCfgReq->threshold);
    486     if (cFramesThreshold >= pCfgObt->buffer_size - pCfgObt->buffer_size / 16)
    487         cFramesThreshold = pCfgObt->buffer_size - pCfgObt->buffer_size / 16;
     486    unsigned long cFramesThreshold = RT_MIN(pAlsaCfgObt->period_size * 2, pAlsaCfgReq->threshold);
     487    if (cFramesThreshold >= pAlsaCfgObt->buffer_size - pAlsaCfgObt->buffer_size / 16)
     488        cFramesThreshold = pAlsaCfgObt->buffer_size - pAlsaCfgObt->buffer_size / 16;
    488489
    489490    err = snd_pcm_sw_params_set_start_threshold(hPCM, pSWParms, cFramesThreshold);
    490491    AssertLogRelMsgReturn(err >= 0, ("ALSA: Failed to set software threshold to %lu: %s\n", cFramesThreshold, snd_strerror(err)), err);
    491492
    492     err = snd_pcm_sw_params_set_avail_min(hPCM, pSWParms, pCfgReq->period_size);
    493     AssertLogRelMsgReturn(err >= 0, ("ALSA: Failed to set available minimum to %lu: %s\n", pCfgReq->period_size, snd_strerror(err)), err);
     493    err = snd_pcm_sw_params_set_avail_min(hPCM, pSWParms, pAlsaCfgReq->period_size);
     494    AssertLogRelMsgReturn(err >= 0, ("ALSA: Failed to set available minimum to %lu: %s\n",
     495                                     pAlsaCfgReq->period_size, snd_strerror(err)), err);
    494496
    495497    /* Commit the software parameters: */
     
    498500
    499501    /* Get the actual parameters: */
    500     err = snd_pcm_sw_params_get_start_threshold(pSWParms, &pCfgObt->threshold);
     502    err = snd_pcm_sw_params_get_start_threshold(pSWParms, &pAlsaCfgObt->threshold);
    501503    AssertLogRelMsgReturn(err >= 0, ("ALSA: Failed to get start threshold: %s\n", snd_strerror(err)), err);
    502504
    503505    LogRel2(("ALSA: SW params: %lu frames threshold, %lu frame avail minimum\n",
    504              pCfgObt->threshold, pCfgReq->period_size));
     506             pAlsaCfgObt->threshold, pAlsaCfgReq->period_size));
    505507    return 0;
    506508}
     
    511513 *
    512514 * @returns 0 on success, negative errno on failure.
    513  * @param   hPCM   ALSA stream to set software parameters for.
    514  * @param   pCfgReq Requested configuration to set.
    515  * @param   pCfgObt Obtained configuration on success. Might differ from
    516  *                  requested configuration.
    517  */
    518 static int alsaStreamSetHwParams(snd_pcm_t *hPCM, PALSAAUDIOSTREAMCFG pCfgReq, PALSAAUDIOSTREAMCFG pCfgObt)
     515 * @param   hPCM        ALSA stream to set software parameters for.
     516 * @param   pAlsaCfgReq Requested configuration to set (ALSA).
     517 * @param   pAlsaCfgObt Obtained configuration on success (ALSA). Might differ
     518 *                      from requested configuration.
     519 */
     520static int alsaStreamSetHwParams(snd_pcm_t *hPCM, PALSAAUDIOSTREAMCFG pAlsaCfgReq, PALSAAUDIOSTREAMCFG pAlsaCfgObt)
    519521{
    520522    /*
     
    529531
    530532    /*
    531      * Modify them according to pCfgReq.
    532      * We update pCfgObt as we go for parameters set by "near" methods.
     533     * Modify them according to pAlsaCfgReq.
     534     * We update pAlsaCfgObt as we go for parameters set by "near" methods.
    533535     */
    534536    /* We'll use snd_pcm_writei/snd_pcm_readi: */
     
    537539
    538540    /* Set the format, frequency and channel count. */
    539     err = snd_pcm_hw_params_set_format(hPCM, pHWParms, pCfgReq->fmt);
    540     AssertLogRelMsgReturn(err >= 0, ("ALSA: Failed to set audio format to %d: %s\n", pCfgReq->fmt, snd_strerror(err)), err);
    541 
    542     unsigned int uFreq = pCfgReq->freq;
     541    err = snd_pcm_hw_params_set_format(hPCM, pHWParms, pAlsaCfgReq->fmt);
     542    AssertLogRelMsgReturn(err >= 0, ("ALSA: Failed to set audio format to %d: %s\n", pAlsaCfgReq->fmt, snd_strerror(err)), err);
     543
     544    unsigned int uFreq = pAlsaCfgReq->freq;
    543545    err = snd_pcm_hw_params_set_rate_near(hPCM, pHWParms, &uFreq, NULL /*dir*/);
    544     AssertLogRelMsgReturn(err >= 0, ("ALSA: Failed to set frequency to %uHz: %s\n", pCfgReq->freq, snd_strerror(err)), err);
    545     pCfgObt->freq      = uFreq;
    546 
    547     unsigned int cChannels = pCfgReq->cChannels;
     546    AssertLogRelMsgReturn(err >= 0, ("ALSA: Failed to set frequency to %uHz: %s\n", pAlsaCfgReq->freq, snd_strerror(err)), err);
     547    pAlsaCfgObt->freq = uFreq;
     548
     549    unsigned int cChannels = pAlsaCfgReq->cChannels;
    548550    err = snd_pcm_hw_params_set_channels_near(hPCM, pHWParms, &cChannels);
    549     AssertLogRelMsgReturn(err >= 0, ("ALSA: Failed to set number of channels to %d\n", pCfgReq->cChannels), err);
    550     pCfgObt->cChannels = cChannels;
     551    AssertLogRelMsgReturn(err >= 0, ("ALSA: Failed to set number of channels to %d\n", pAlsaCfgReq->cChannels), err);
     552    pAlsaCfgObt->cChannels = cChannels;
    551553
    552554    /* The period size (reportedly frame count per hw interrupt): */
    553555    int               dir    = 0;
    554     snd_pcm_uframes_t minval = pCfgReq->period_size;
     556    snd_pcm_uframes_t minval = pAlsaCfgReq->period_size;
    555557    err = snd_pcm_hw_params_get_period_size_min(pHWParms, &minval, &dir);
    556558    AssertLogRelMsgReturn(err >= 0, ("ALSA: Could not determine minimal period size: %s\n", snd_strerror(err)), err);
    557559
    558     snd_pcm_uframes_t period_size_f = pCfgReq->period_size;
     560    snd_pcm_uframes_t period_size_f = pAlsaCfgReq->period_size;
    559561    if (period_size_f < minval)
    560562        period_size_f = minval;
    561563    err = snd_pcm_hw_params_set_period_size_near(hPCM, pHWParms, &period_size_f, 0);
    562     LogRel2(("ALSA: Period size is: %lu frames (min %lu, requested %lu)\n", period_size_f, minval, pCfgReq->period_size));
     564    LogRel2(("ALSA: Period size is: %lu frames (min %lu, requested %lu)\n", period_size_f, minval, pAlsaCfgReq->period_size));
    563565    AssertLogRelMsgReturn(err >= 0, ("ALSA: Failed to set period size %d (%s)\n", period_size_f, snd_strerror(err)), err);
    564566
    565567    /* The buffer size: */
    566     minval = pCfgReq->buffer_size;
     568    minval = pAlsaCfgReq->buffer_size;
    567569    err = snd_pcm_hw_params_get_buffer_size_min(pHWParms, &minval);
    568570    AssertLogRelMsgReturn(err >= 0, ("ALSA: Could not retrieve minimal buffer size: %s\n", snd_strerror(err)), err);
    569571
    570     snd_pcm_uframes_t buffer_size_f = pCfgReq->buffer_size;
     572    snd_pcm_uframes_t buffer_size_f = pAlsaCfgReq->buffer_size;
    571573    if (buffer_size_f < minval)
    572574        buffer_size_f = minval;
    573575    err = snd_pcm_hw_params_set_buffer_size_near(hPCM, pHWParms, &buffer_size_f);
    574     LogRel2(("ALSA: Buffer size is: %lu frames (min %lu, requested %lu)\n", buffer_size_f, minval, pCfgReq->buffer_size));
     576    LogRel2(("ALSA: Buffer size is: %lu frames (min %lu, requested %lu)\n", buffer_size_f, minval, pAlsaCfgReq->buffer_size));
    575577    AssertLogRelMsgReturn(err >= 0, ("ALSA: Failed to set near buffer size %RU32: %s\n", buffer_size_f, snd_strerror(err)), err);
    576578
     
    582584
    583585    /*
    584      * Get relevant parameters and put them in the pCfgObt structure.
     586     * Get relevant parameters and put them in the pAlsaCfgObt structure.
    585587     */
    586588    snd_pcm_uframes_t obt_buffer_size = buffer_size_f;
    587589    err = snd_pcm_hw_params_get_buffer_size(pHWParms, &obt_buffer_size);
    588590    AssertLogRelMsgStmt(err >= 0, ("ALSA: Failed to get buffer size: %s\n", snd_strerror(err)), obt_buffer_size = buffer_size_f);
    589     pCfgObt->buffer_size = obt_buffer_size;
     591    pAlsaCfgObt->buffer_size = obt_buffer_size;
    590592
    591593    snd_pcm_uframes_t obt_period_size = period_size_f;
    592594    err = snd_pcm_hw_params_get_period_size(pHWParms, &obt_period_size, &dir);
    593595    AssertLogRelMsgStmt(err >= 0, ("ALSA: Failed to get period size: %s\n", snd_strerror(err)), obt_period_size = period_size_f);
    594     pCfgObt->period_size = obt_period_size;
    595 
    596 //    pCfgObt->access  = pCfgReq->access;  - unused and uninitialized.
    597     pCfgObt->fmt     = pCfgReq->fmt;
     596    pAlsaCfgObt->period_size = obt_period_size;
     597
     598//    pAlsaCfgObt->access  = pAlsaCfgReq->access;  - unused and uninitialized.
     599    pAlsaCfgObt->fmt     = pAlsaCfgReq->fmt;
    598600
    599601    LogRel2(("ALSA: HW params: %u Hz, %lu frames period, %lu frames buffer, %u channel(s), fmt=%d, access=%d\n",
    600              pCfgObt->freq, pCfgObt->period_size, pCfgObt->buffer_size, pCfgObt->cChannels, pCfgObt->fmt, -1 /*pCfgObt->access*/));
     602             pAlsaCfgObt->freq, pAlsaCfgObt->period_size, pAlsaCfgObt->buffer_size, pAlsaCfgObt->cChannels,
     603             pAlsaCfgObt->fmt, -1 /*pAlsaCfgObt->access*/));
    601604    return 0;
    602605}
     
    607610 *
    608611 * @returns VBox status code.
    609  * @param   pszDev  The name of the device to open.
    610  * @param   fIn     Whether this is an input stream to create or not.
    611  * @param   pCfgReq Requested configuration to create stream with.
    612  * @param   pCfgObt Obtained configuration the stream got created on success.
    613  * @param   phPCM   Where to store the ALSA stream handle on success.
    614  */
    615 static int alsaStreamOpen(const char *pszDev, bool fIn, PALSAAUDIOSTREAMCFG pCfgReq,
    616                           PALSAAUDIOSTREAMCFG pCfgObt,  snd_pcm_t **phPCM)
     612 * @param   pszDev      The name of the device to open.
     613 * @param   fIn         Whether this is an input stream to create or not.
     614 * @param   pAlsaCfgReq Requested configuration to create stream with (ALSA).
     615 * @param   pCfgReq     Requested configuration to create stream with (PDM).
     616 * @param   pAlsaCfgObt Obtained configuration the stream got created on
     617 *                      success.
     618 * @param   phPCM       Where to store the ALSA stream handle on success.
     619 */
     620static int alsaStreamOpen(const char *pszDev, bool fIn, PALSAAUDIOSTREAMCFG pAlsaCfgReq, PPDMAUDIOSTREAMCFG pCfgReq,
     621                          PALSAAUDIOSTREAMCFG pAlsaCfgObt,  snd_pcm_t **phPCM)
    617622{
    618623    AssertLogRelMsgReturn(pszDev && *pszDev,
    619624                          ("ALSA: Invalid or no %s device name set\n", fIn ? "input" : "output"),
    620625                          VERR_INVALID_NAME);
     626    RT_NOREF(pCfgReq);
    621627
    622628    /*
     
    637643             * Configure hardware stream parameters.
    638644             */
    639             err = alsaStreamSetHwParams(hPCM, pCfgReq, pCfgObt);
     645            err = alsaStreamSetHwParams(hPCM, pAlsaCfgReq, pAlsaCfgObt);
    640646            if (err >= 0)
    641647            {
     
    650656                     * Configure software stream parameters and we're done.
    651657                     */
    652                     rc = alsaStreamSetSWParams(hPCM, fIn, pCfgReq, pCfgObt);
     658                    rc = alsaStreamSetSWParams(hPCM, fIn, pAlsaCfgReq, pAlsaCfgObt);
    653659                    if (RT_SUCCESS(rc))
    654660                    {
     
    673679
    674680/**
    675  * Creates an ALSA output stream.
    676  *
    677  * @returns VBox status code.
    678  * @param   pThis       The ALSA driver instance data.
    679  * @param   pStreamALSA ALSA output stream to create.
    680  * @param   pCfgReq     Requested configuration to create stream with.
    681  * @param   pCfgAcq     Obtained configuration the stream got created
    682  *                      with on success.
    683  */
    684 static int alsaCreateStreamOut(PDRVHOSTALSAAUDIO pThis, PALSAAUDIOSTREAM pStreamALSA,
    685                                PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    686 {
     681 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
     682 */
     683static DECLCALLBACK(int) drvHostAlsaAudioHA_StreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
     684                                                         PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
     685{
     686    PDRVHOSTALSAAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVHOSTALSAAUDIO, IHostAudio);
     687    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     688    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     689    AssertPtrReturn(pCfgReq,    VERR_INVALID_POINTER);
     690    AssertPtrReturn(pCfgAcq,    VERR_INVALID_POINTER);
     691
     692    PALSAAUDIOSTREAM pStreamALSA = (PALSAAUDIOSTREAM)pStream;
     693    PDMAudioStrmCfgCopy(&pStreamALSA->Cfg, pCfgReq);
     694
    687695    ALSAAUDIOSTREAMCFG Req;
    688696    Req.fmt         = alsaAudioPropsToALSA(&pCfgReq->Props);
     
    692700    Req.buffer_size = pCfgReq->Backend.cFramesBufferSize;
    693701    Req.threshold   = PDMAudioPropsMilliToFrames(&pCfgReq->Props, 50);
    694     int rc = alsaStreamOpen(pThis->szDefaultOut, false /*fIn*/, &Req, &pStreamALSA->AlsaCfg, &pStreamALSA->hPCM);
     702    int rc = alsaStreamOpen(pCfgReq->enmDir == PDMAUDIODIR_IN ? pThis->szDefaultIn : pThis->szDefaultOut,
     703                            pCfgReq->enmDir == PDMAUDIODIR_IN,
     704                            &Req, pCfgReq, &pStreamALSA->AlsaCfg, &pStreamALSA->hPCM);
    695705    if (RT_SUCCESS(rc))
    696706    {
     
    704714            /* We have no objections to the pre-buffering that DrvAudio applies,
    705715               only we need to adjust it relative to the actual buffer size. */
    706             /** @todo DrvAudio should do this. */
    707716            pCfgAcq->Backend.cFramesPreBuffering    = (uint64_t)pCfgReq->Backend.cFramesPreBuffering
    708717                                                    * pCfgAcq->Backend.cFramesBufferSize
    709718                                                    / RT_MAX(pCfgReq->Backend.cFramesBufferSize, 1);
    710719
     720            PDMAudioStrmCfgCopy(&pStreamALSA->Cfg, pCfgAcq);
    711721            LogFlowFunc(("returns success - hPCM=%p\n", pStreamALSA->hPCM));
    712             return VINF_SUCCESS;
     722            return rc;
    713723        }
    714724        alsaStreamClose(&pStreamALSA->hPCM);
    715725    }
    716     LogFlowFuncLeaveRC(rc);
    717     return rc;
    718 }
    719 
    720 
    721 /**
    722  * Creates an ALSA input stream.
    723  *
    724  * @returns VBox status code.
    725  * @param   pThis       The ALSA driver instance data.
    726  * @param   pStreamALSA ALSA input stream to create.
    727  * @param   pCfgReq     Requested configuration to create stream with.
    728  * @param   pCfgAcq     Obtained configuration the stream got created
    729  *                      with on success.
    730  */
    731 static int alsaCreateStreamIn(PDRVHOSTALSAAUDIO pThis, PALSAAUDIOSTREAM pStreamALSA,
    732                               PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    733 {
    734     ALSAAUDIOSTREAMCFG Req;
    735     Req.fmt         = alsaAudioPropsToALSA(&pCfgReq->Props);
    736     Req.freq        = PDMAudioPropsHz(&pCfgReq->Props);
    737     Req.cChannels   = PDMAudioPropsChannels(&pCfgReq->Props);
    738 /** @todo r=bird: Isn't all this configurable already?!?   */
    739     Req.period_size = PDMAudioPropsMilliToFrames(&pCfgReq->Props, 50 /*ms*/); /** @todo Make this configurable. */
    740     Req.buffer_size = Req.period_size * 2; /** @todo Make this configurable. */
    741     Req.threshold   = Req.period_size;
    742     int rc = alsaStreamOpen(pThis->szDefaultIn, true /* fIn */, &Req, &pStreamALSA->AlsaCfg, &pStreamALSA->hPCM);
    743     if (RT_SUCCESS(rc))
    744     {
    745         rc = alsaALSAToAudioProps(&pCfgAcq->Props, pStreamALSA->AlsaCfg.fmt, pStreamALSA->AlsaCfg.cChannels, pStreamALSA->AlsaCfg.freq);
    746         if (RT_SUCCESS(rc))
    747         {
    748             pCfgAcq->Backend.cFramesPeriod       = pStreamALSA->AlsaCfg.period_size;
    749             pCfgAcq->Backend.cFramesBufferSize   = pStreamALSA->AlsaCfg.buffer_size;
    750             pCfgAcq->Backend.cFramesPreBuffering = 0; /* No pre-buffering. */
    751             return VINF_SUCCESS;
    752         }
    753 
    754         alsaStreamClose(&pStreamALSA->hPCM);
    755     }
    756     LogFlowFuncLeaveRC(rc);
    757     return rc;
    758 }
    759 
    760 
    761 /**
    762  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
    763  */
    764 static DECLCALLBACK(int) drvHostAlsaAudioHA_StreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
    765                                                          PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    766 {
    767     PDRVHOSTALSAAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVHOSTALSAAUDIO, IHostAudio);
    768     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    769     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    770     AssertPtrReturn(pCfgReq,    VERR_INVALID_POINTER);
    771     AssertPtrReturn(pCfgAcq,    VERR_INVALID_POINTER);
    772 
    773     PALSAAUDIOSTREAM pStreamALSA = (PALSAAUDIOSTREAM)pStream;
    774     PDMAudioStrmCfgCopy(&pStreamALSA->Cfg, pCfgReq);
    775 
    776     int rc;
    777     if (pCfgReq->enmDir == PDMAUDIODIR_IN)
    778         rc = alsaCreateStreamIn( pThis, pStreamALSA, pCfgReq, pCfgAcq);
    779     else
    780         rc = alsaCreateStreamOut(pThis, pStreamALSA, pCfgReq, pCfgAcq);
    781     if (RT_SUCCESS(rc))
    782         PDMAudioStrmCfgCopy(&pStreamALSA->Cfg, pCfgAcq);
     726    LogFunc(("returns %Rrc\n", rc));
    783727    return rc;
    784728}
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