VirtualBox

Changeset 89471 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Jun 2, 2021 8:53:43 PM (4 years ago)
Author:
vboxsync
Message:

DrvHostAudioAlsa: Use snd_pcm_set_chmap to identify the channels we're outputting. bugref:9890

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

Legend:

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

    r89470 r89471  
    418418
    419419/**
     420 * Maps a PDM channel ID to an ASLA channel map position.
     421 */
     422static unsigned int drvHstAudAlsaPdmChToAlsa(PDMAUDIOCHANNELID enmId, uint8_t cChannels)
     423{
     424    switch (enmId)
     425    {
     426        case PDMAUDIOCHANNELID_UNKNOWN:                 return SND_CHMAP_UNKNOWN;
     427        case PDMAUDIOCHANNELID_UNUSED_ZERO:             return SND_CHMAP_NA;
     428        case PDMAUDIOCHANNELID_UNUSED_SILENCE:          return SND_CHMAP_NA;
     429
     430        case PDMAUDIOCHANNELID_FRONT_LEFT:              return SND_CHMAP_FL;
     431        case PDMAUDIOCHANNELID_FRONT_RIGHT:             return SND_CHMAP_FR;
     432        case PDMAUDIOCHANNELID_FRONT_CENTER:            return cChannels == 1 ? SND_CHMAP_MONO : SND_CHMAP_FC;
     433        case PDMAUDIOCHANNELID_LFE:                     return SND_CHMAP_LFE;
     434        case PDMAUDIOCHANNELID_REAR_LEFT:               return SND_CHMAP_RL;
     435        case PDMAUDIOCHANNELID_REAR_RIGHT:              return SND_CHMAP_RR;
     436        case PDMAUDIOCHANNELID_FRONT_LEFT_OF_CENTER:    return SND_CHMAP_FLC;
     437        case PDMAUDIOCHANNELID_FRONT_RIGHT_OF_CENTER:   return SND_CHMAP_FRC;
     438        case PDMAUDIOCHANNELID_REAR_CENTER:             return SND_CHMAP_RC;
     439        case PDMAUDIOCHANNELID_SIDE_LEFT:               return SND_CHMAP_SL;
     440        case PDMAUDIOCHANNELID_SIDE_RIGHT:              return SND_CHMAP_SR;
     441        case PDMAUDIOCHANNELID_TOP_CENTER:              return SND_CHMAP_TC;
     442        case PDMAUDIOCHANNELID_FRONT_LEFT_HEIGHT:       return SND_CHMAP_TFL;
     443        case PDMAUDIOCHANNELID_FRONT_CENTER_HEIGHT:     return SND_CHMAP_TFC;
     444        case PDMAUDIOCHANNELID_FRONT_RIGHT_HEIGHT:      return SND_CHMAP_TFR;
     445        case PDMAUDIOCHANNELID_REAR_LEFT_HEIGHT:        return SND_CHMAP_TRL;
     446        case PDMAUDIOCHANNELID_REAR_CENTER_HEIGHT:      return SND_CHMAP_TRC;
     447        case PDMAUDIOCHANNELID_REAR_RIGHT_HEIGHT:       return SND_CHMAP_TRR;
     448
     449        case PDMAUDIOCHANNELID_INVALID:
     450        case PDMAUDIOCHANNELID_END:
     451        case PDMAUDIOCHANNELID_32BIT_HACK:
     452            break;
     453    }
     454    AssertFailed();
     455    return SND_CHMAP_NA;
     456}
     457
     458
     459/**
    420460 * Sets the hardware parameters of an ALSA stream.
    421461 *
     
    451491    AssertLogRelMsgReturn(err >= 0, ("ALSA: Failed to set access type: %s\n", snd_strerror(err)), err);
    452492
    453     /* Set the format, frequency and channel count. */
     493    /* Set the format and frequency. */
    454494    err = snd_pcm_hw_params_set_format(hPCM, pHWParms, enmAlsaFmt);
    455495    AssertLogRelMsgReturn(err >= 0, ("ALSA: Failed to set audio format to %d: %s\n", enmAlsaFmt, snd_strerror(err)), err);
     
    461501    pCfgAcq->Props.uHz = uFreq;
    462502
    463     unsigned int cChannels = PDMAudioPropsChannels(&pCfgReq->Props);
     503    /* Channel count currently does not change with the mapping translations,
     504       as ALSA can express both silent and unknown channel positions. */
     505    union
     506    {
     507        snd_pcm_chmap_t Map;
     508        unsigned int    padding[1 + PDMAUDIO_MAX_CHANNELS];
     509    } u;
     510    uint8_t      aidChannels[PDMAUDIO_MAX_CHANNELS];
     511    unsigned int cChannels = u.Map.channels = PDMAudioPropsChannels(&pCfgReq->Props);
     512    unsigned int iDst      = 0;
     513    for (unsigned int iSrc = 0; iSrc < cChannels; iSrc++)
     514    {
     515        uint8_t const idSrc = pCfgReq->Props.aidChannels[iSrc];
     516        aidChannels[iDst] = idSrc;
     517        u.Map.pos[iDst]   = drvHstAudAlsaPdmChToAlsa((PDMAUDIOCHANNELID)idSrc, cChannels);
     518        iDst++;
     519    }
     520    u.Map.channels = cChannels = iDst;
     521    for (; iDst < PDMAUDIO_MAX_CHANNELS; iDst++)
     522    {
     523        aidChannels[iDst] = PDMAUDIOCHANNELID_INVALID;
     524        u.Map.pos[iDst]   = SND_CHMAP_NA;
     525    }
     526
    464527    err = snd_pcm_hw_params_set_channels_near(hPCM, pHWParms, &cChannels);
    465528    AssertLogRelMsgReturn(err >= 0, ("ALSA: Failed to set number of channels to %d\n", PDMAudioPropsChannels(&pCfgReq->Props)),
    466529                          err);
    467     if (cChannels != PDMAudioPropsChannels(&pCfgReq->Props))
    468     {
     530    if (cChannels == PDMAudioPropsChannels(&pCfgReq->Props))
     531        memcpy(pCfgAcq->Props.aidChannels, aidChannels, sizeof(pCfgAcq->Props.aidChannels));
     532    else
     533    {
     534        LogRel2(("ALSA: Requested %u channels, got %u\n", u.Map.channels, cChannels));
    469535        AssertLogRelMsgReturn(cChannels > 0 && cChannels <= PDMAUDIO_MAX_CHANNELS,
    470536                              ("ALSA: Unsupported channel count: %u (requested %d)\n",
    471537                               cChannels, PDMAudioPropsChannels(&pCfgReq->Props)), -ERANGE);
    472538        PDMAudioPropsSetChannels(&pCfgAcq->Props, (uint8_t)cChannels);
    473         /** @todo Can we somehow guess channel IDs? */
     539        /** @todo Can we somehow guess channel IDs? snd_pcm_get_chmap? */
    474540    }
    475541
     
    521587             PDMAudioPropsHz(&pCfgAcq->Props), pCfgAcq->Backend.cFramesPeriod, pCfgAcq->Backend.cFramesBufferSize,
    522588             PDMAudioPropsChannels(&pCfgAcq->Props), enmAlsaFmt));
     589
     590    /*
     591     * Channel config (not fatal).
     592     */
     593    if (PDMAudioPropsChannels(&pCfgAcq->Props) == PDMAudioPropsChannels(&pCfgReq->Props))
     594    {
     595        err = snd_pcm_set_chmap(hPCM, &u.Map);
     596        if (err < 0)
     597            LogRel2(("ALSA: snd_pcm_set_chmap failed: %s (%d)\n", snd_strerror(err), err));
     598    }
     599
    523600    return 0;
    524601}
     
    572649                {
    573650                    /*
    574                      * Configure software stream parameters and we're done.
     651                     * Configure software stream parameters.
    575652                     */
    576653                    rc = alsaStreamSetSWParams(hPCM, pCfgReq, pCfgAcq);
  • trunk/src/VBox/Devices/Audio/DrvHostAudioAlsaStubs.cpp

    r89427 r89471  
    9595           (pcm, buffer, size))
    9696PROXY_STUB(snd_pcm_resume, int, (snd_pcm_t *pcm), (pcm))
     97PROXY_STUB(snd_pcm_set_chmap, int, (snd_pcm_t *pcm, snd_pcm_chmap_t const *map), (pcm, map))
    9798PROXY_STUB(snd_pcm_state, snd_pcm_state_t, (snd_pcm_t *pcm), (pcm))
    9899PROXY_STUB(snd_pcm_state_name, const char *, (snd_pcm_state_t state), (state))
     
    109110        ret = (int)*availp;
    110111    return ret;
     112}
     113
     114static int fallback_snd_pcm_set_chmap(snd_pcm_t *pcm, snd_pcm_chmap_t const *map)
     115{
     116    RT_NOREF(pcm, map);
     117    return 0;
    111118}
    112119
     
    208215    ELEMENT(snd_pcm_prepare),
    209216    ELEMENT(snd_pcm_resume),
     217    ELEMENT_FALLBACK(snd_pcm_set_chmap),
    210218    ELEMENT(snd_pcm_state),
    211219    ELEMENT(snd_pcm_state_name),
  • trunk/src/VBox/Devices/Audio/DrvHostAudioAlsaStubs.h

    r89099 r89471  
    2525#include <alsa/version.h>
    2626
     27#define VBOX_ALSA_MAKE_VER(a,b,c)   ( ((a) << 24) | ((b) << 16) | (a) )
     28#define VBOX_ALSA_VER               VBOX_ALSA_MAKE_VER(SND_LIB_MAJOR, SND_LIB_MINOR, SND_LIB_SUBMINOR)
     29
    2730RT_C_DECLS_BEGIN
    2831extern int audioLoadAlsaLib(void);
    2932
    30 #if (((SND_LIB_MAJOR) << 16) | ((SND_LIB_MAJOR) << 8) | (SND_LIB_SUBMINOR)) >= 0x10000 /* was added in 1.0.0 */
     33#if VBOX_ALSA_VER < VBOX_ALSA_MAKE_VER(1,0,0)   /* added in 1.0.0 */
    3134extern int  snd_pcm_avail_delay(snd_pcm_t *, snd_pcm_sframes_t *, snd_pcm_sframes_t *);
    3235#endif
    3336
    34 #if (((SND_LIB_MAJOR) << 16) | ((SND_LIB_MAJOR) << 8) | (SND_LIB_SUBMINOR)) >= 0x1000e /* was added in 1.0.14a */
     37#if VBOX_ALSA_VER < VBOX_ALSA_MAKE_VER(1,0,14)  /* added in 1.0.14a */
    3538extern int  snd_device_name_hint(int, const char *, void ***);
    3639extern int  snd_device_name_free_hint(void **);
    3740extern char *snd_device_name_get_hint(const void *, const char *);
     41#endif
     42
     43#if VBOX_ALSA_VER < VBOX_ALSA_MAKE_VER(1,0,27)  /* added in 1.0.27 */
     44enum snd_pcm_chmap_position { SND_CHMAP_UNKNOWN = 0, SND_CHMAP_NA, SND_CHMAP_MONO, SND_CHMAP_FL, SND_CHMAP_FR,
     45    SND_CHMAP_RL,  SND_CHMAP_RR,   SND_CHMAP_FC,   SND_CHMAP_LFE,  SND_CHMAP_SL,  SND_CHMAP_SR,  SND_CHMAP_RC,
     46    SND_CHMAP_FLC, SND_CHMAP_FRC,  SND_CHMAP_RLC,  SND_CHMAP_RRC,  SND_CHMAP_FLW, SND_CHMAP_FRW, SND_CHMAP_FLH,
     47    SND_CHMAP_FCH, SND_CHMAP_FRH,  SND_CHMAP_TC,   SND_CHMAP_TFL,  SND_CHMAP_TFR, SND_CHMAP_TFC, SND_CHMAP_TRL,
     48    SND_CHMAP_TRR, SND_CHMAP_TRC,  SND_CHMAP_TFLC, SND_CHMAP_TFRC, SND_CHMAP_TSL, SND_CHMAP_TSR, SND_CHMAP_LLFE,
     49    SND_CHMAP_RLFE, SND_CHMAP_BC,  SND_CHMAP_BLC,  SND_CHMAP_BRC };
     50typedef struct snd_pcm_chmap
     51{
     52    unsigned int channels, pos[0];
     53} snd_pcm_chmap_t;
     54extern int snd_pcm_set_chmap(snd_pcm_t *, const snd_pcm_chmap_t *);
    3855#endif
    3956
  • trunk/src/VBox/Devices/Audio/DrvHostAudioAlsaStubsMangling.h

    r88966 r89471  
    4444#define snd_pcm_readi                           ALSA_MANGLER(snd_pcm_readi)
    4545#define snd_pcm_resume                          ALSA_MANGLER(snd_pcm_resume)
     46#define snd_pcm_set_chmap                       ALSA_MANGLER(snd_pcm_set_chmap)
    4647#define snd_pcm_start                           ALSA_MANGLER(snd_pcm_start)
    4748#define snd_pcm_state                           ALSA_MANGLER(snd_pcm_state)
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