VirtualBox

Changeset 88269 in vbox for trunk/src/VBox/Main/src-client


Ignore:
Timestamp:
Mar 24, 2021 11:45:54 AM (4 years ago)
Author:
vboxsync
Message:

Audio: Made sure PDMAUDIOPCMPROPS is initialized using a helper function or the initializer macro, and that vital changes are made using setting helper functions. There are now two derived fields (frame size and shift count) that must be maintained, so this was the sanest way of doing it. Added a raw flag to PDMAUDIOPCMPROPS for VRDE/VRDP, since it wants the raw mixer content and we need a way of expressing this (PDMAUDIOSTREAMLAYOUT isn't the right place). The mixer buffers now uses PDMAUDIOPCMPROPS rather than the weird 32-bit format contraption for picking conversion functions. Simplify the drvAudioStreamPlay code by eliminating the PDMAUDIOSTREAMLAYOUT_RAW special case. bugref:9890

Location:
trunk/src/VBox/Main/src-client
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-client/AudioDriver.cpp

    r82968 r88269  
    230230                               "AUDIO", 0 /* iOccurrence */,  0 /* fFlags */);
    231231    if (RT_SUCCESS(rc))
    232         rc = pThis->configure(pCfg->uLUN, false /* Detach */);
     232        rc = pThis->configure(pCfg->uLUN, false /* Detach */);/** @todo r=bird: Illogical and from what I can tell pointless! */
    233233
    234234    if (RT_SUCCESS(rc))
  • trunk/src/VBox/Main/src-client/DrvAudioRec.cpp

    r88030 r88269  
    304304static int avRecSinkInit(PDRVAUDIORECORDING pThis, PAVRECSINK pSink, PAVRECCONTAINERPARMS pConParms, PAVRECCODECPARMS pCodecParms)
    305305{
    306     uint32_t uHz       = pCodecParms->PCMProps.uHz;
    307     uint8_t  cBytes    = pCodecParms->PCMProps.cbSample;
    308     uint8_t  cChannels = pCodecParms->PCMProps.cChannels;
    309     uint32_t uBitrate  = pCodecParms->uBitrate;
     306    uint32_t       uHz       = PDMAudioPropsHz(&pCodecParms->PCMProps);
     307    uint8_t const  cbSample  = PDMAudioPropsSampleSize(&pCodecParms->PCMProps);
     308    uint8_t        cChannels = PDMAudioPropsChannels(&pCodecParms->PCMProps);
     309    uint32_t       uBitrate  = pCodecParms->uBitrate;
    310310
    311311    /* Opus only supports certain input sample rates in an efficient manner.
     
    391391                    if (RT_SUCCESS(rc))
    392392                    {
    393                         rc = pSink->Con.WebM.pWebM->AddAudioTrack(uHz, cChannels, cBytes * 8 /* Bits */,
     393                        rc = pSink->Con.WebM.pWebM->AddAudioTrack(uHz, cChannels, cbSample * 8 /* Bits */,
    394394                                                                  &pSink->Con.WebM.uTrack);
    395395                        if (RT_SUCCESS(rc))
     
    422422        PAVRECCODEC pCodec = &pSink->Codec;
    423423
    424         pCodec->Parms.PCMProps.uHz       = uHz;
    425         pCodec->Parms.PCMProps.cChannels = cChannels;
    426         pCodec->Parms.PCMProps.cbSample  = cBytes;
    427         pCodec->Parms.PCMProps.cShift    = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pSink->Codec.Parms.PCMProps.cbSample,
    428                                                                              pSink->Codec.Parms.PCMProps.cChannels);
    429         pCodec->Parms.uBitrate           = uBitrate;
     424        PDMAudioPropsInit(&pCodec->Parms.PCMProps, cbSample, pCodecParms->PCMProps.fSigned, cChannels, uHz);
     425        pCodec->Parms.uBitrate  = uBitrate;
    430426
    431427        pCodec->Opus.pEnc       = pEnc;
     
    543539                pStreamAV->uLastPTSMs = 0;
    544540
    545                 if (pCfgAcq)
    546                 {
    547                     /* Make sure to let the driver backend know that we need the audio data in
    548                      * a specific sampling rate Opus is optimized for. */
    549                     pCfgAcq->Props.uHz         = pSink->Codec.Parms.PCMProps.uHz;
    550                     pCfgAcq->Props.cShift      = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfgAcq->Props.cbSample, pCfgAcq->Props.cChannels);
    551 
    552                     /* Every Opus frame marks a period for now. Optimize this later. */
    553                     pCfgAcq->Backend.cFramesPeriod       = PDMAudioPropsMilliToFrames(&pCfgAcq->Props, pSink->Codec.Opus.msFrame);
    554                     pCfgAcq->Backend.cFramesBufferSize   = PDMAudioPropsMilliToFrames(&pCfgAcq->Props, 100 /*ms*/); /** @todo Make this configurable. */
    555                     pCfgAcq->Backend.cFramesPreBuffering = pCfgAcq->Backend.cFramesPeriod * 2;
    556                 }
     541                /* Make sure to let the driver backend know that we need the audio data in
     542                 * a specific sampling rate Opus is optimized for. */
     543/** @todo r=bird: pCfgAcq->Props isn't initialized at all, except for uHz... */
     544                pCfgAcq->Props.uHz         = pSink->Codec.Parms.PCMProps.uHz;
     545//                pCfgAcq->Props.cShift      = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfgAcq->Props.cbSample, pCfgAcq->Props.cChannels);
     546
     547                /* Every Opus frame marks a period for now. Optimize this later. */
     548                pCfgAcq->Backend.cFramesPeriod       = PDMAudioPropsMilliToFrames(&pCfgAcq->Props, pSink->Codec.Opus.msFrame);
     549                pCfgAcq->Backend.cFramesBufferSize   = PDMAudioPropsMilliToFrames(&pCfgAcq->Props, 100 /*ms*/); /** @todo Make this configurable. */
     550                pCfgAcq->Backend.cFramesPreBuffering = pCfgAcq->Backend.cFramesPeriod * 2;
    557551            }
    558552            else
     
    651645    PDRVAUDIORECORDING pThis = PDMIHOSTAUDIO_2_DRVAUDIORECORDING(pInterface);
    652646
    653     LogRel(("Recording: Audio driver is using %RU32Hz, %RU16bit, %RU8 %s\n",
    654             pThis->CodecParms.PCMProps.uHz, pThis->CodecParms.PCMProps.cbSample * 8,
    655             pThis->CodecParms.PCMProps.cChannels, pThis->CodecParms.PCMProps.cChannels == 1 ? "channel" : "channels"));
     647    LogRel(("Recording: Audio driver is using %RU32Hz, %RU16bit, %RU8 channel%s\n",
     648            PDMAudioPropsHz(&pThis->CodecParms.PCMProps), PDMAudioPropsSampleBits(&pThis->CodecParms.PCMProps),
     649            PDMAudioPropsChannels(&pThis->CodecParms.PCMProps), PDMAudioPropsChannels(&pThis->CodecParms.PCMProps) == 1 ? "" : "s"));
    656650
    657651    int rc = avRecSinkInit(pThis, &pThis->Sink, &pThis->ContainerParms, &pThis->CodecParms);
    658652    if (RT_FAILURE(rc))
    659     {
    660653        LogRel(("Recording: Audio recording driver failed to initialize, rc=%Rrc\n", rc));
    661     }
    662654    else
    663655        LogRel2(("Recording: Audio recording driver initialized\n"));
     
    11971189    PAVRECCONTAINERPARMS pConParams  = &pThis->ContainerParms;
    11981190    PAVRECCODECPARMS     pCodecParms = &pThis->CodecParms;
    1199     PPDMAUDIOPCMPROPS    pPCMProps   = &pCodecParms->PCMProps;
    12001191
    12011192    RT_ZERO(pThis->ContainerParms);
     
    12161207    }
    12171208
    1218     rc = CFGMR3QueryU32(pCfg, "CodecHz", &pPCMProps->uHz);
     1209    uint32_t uHz = 0;
     1210    rc = CFGMR3QueryU32(pCfg, "CodecHz", &uHz);
    12191211    AssertRCReturn(rc, rc);
    1220     rc = CFGMR3QueryU8(pCfg,  "CodecBits", &pPCMProps->cbSample); /** @todo CodecBits != CodecBytes */
     1212
     1213    uint8_t cSampleBits = 0;
     1214    rc = CFGMR3QueryU8(pCfg,  "CodecBits", &cSampleBits); /** @todo CodecBits != CodecBytes */
    12211215    AssertRCReturn(rc, rc);
    1222     pPCMProps->cbSample /= 8; /* Bits to bytes. */
    1223     rc = CFGMR3QueryU8(pCfg,  "CodecChannels", &pPCMProps->cChannels);
     1216
     1217    uint8_t cChannels = 0;
     1218    rc = CFGMR3QueryU8(pCfg,  "CodecChannels", &cChannels);
    12241219    AssertRCReturn(rc, rc);
     1220
     1221    PDMAudioPropsInit(&pCodecParms->PCMProps, cSampleBits / 8, true /*fSigned*/, cChannels, uHz);
     1222    AssertMsgReturn(PDMAudioPropsAreValid(&pCodecParms->PCMProps),
     1223                    ("Configuration error: Audio configuration is invalid!\n"), VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES); /** @todo wrong status code. */
     1224
    12251225    rc = CFGMR3QueryU32(pCfg, "CodecBitrate", &pCodecParms->uBitrate);
    12261226    AssertRCReturn(rc, rc);
    1227 
    1228     pPCMProps->cShift      = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pPCMProps->cbSample, pPCMProps->cChannels);
    1229     pPCMProps->fSigned     = true;
    1230     pPCMProps->fSwapEndian = false;
    1231 
    1232     AssertMsgReturn(PDMAudioPropsAreValid(pPCMProps),
    1233                     ("Configuration error: Audio configuration is invalid!\n"), VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES);
    12341227
    12351228    pThis->pAudioVideoRec = (AudioVideoRec *)pvUser;
  • trunk/src/VBox/Main/src-client/DrvAudioVRDE.cpp

    r88255 r88269  
    8484    AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER);
    8585
    86     pCfgAcq->Props.uHz         = 22050; /* The VRDP server's internal frequency. */
    87     pCfgAcq->Props.cChannels   = 2;
    88     pCfgAcq->Props.cbSample    = 2; /* 16 bit. */
    89     pCfgAcq->Props.fSigned     = true;
    90     pCfgAcq->Props.fSwapEndian = false;
    91     pCfgAcq->Props.cShift      = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfgAcq->Props.cbSample, pCfgAcq->Props.cChannels);
     86    /*
     87     * The VRDP server does its own mixing and resampling as it may server
     88     * multiple clients all with different sound formats.  So, it feeds us
     89     * raw mixer frames (somewhat akind to stereo signed 64-bit, see
     90     * st_sample_t and PDMAUDIOFRAME).
     91     */
     92    pCfgAcq->enmLayout = PDMAUDIOSTREAMLAYOUT_RAW;
     93    PDMAudioPropsInitEx(&pCfgAcq->Props, 8 /*64-bit*/, true /*fSigned*/, 2 /*stereo*/, 22050 /*Hz*/,
     94                        true /*fLittleEndian*/, true /*fRaw*/);
    9295
    9396    /* According to the VRDP docs, the VRDP server stores audio in 200ms chunks. */
     
    97100    if (RT_SUCCESS(rc))
    98101    {
    99         /*
    100          * Because of historical reasons the VRDP server operates on st_sample_t structures internally,
    101          * which is 2 * int64_t for left/right (stereo) channels.
    102          *
    103          * As the audio connector also uses this format, set the layout to "raw" and just let pass through
    104          * the data without any layout modification needed.
    105          */
    106         pCfgAcq->enmLayout                      = PDMAUDIOSTREAMLAYOUT_RAW;
    107102        pCfgAcq->Backend.cFramesPeriod          = cFramesVrdpServer;
    108103/** @todo r=bird: This is inconsistent with the above buffer allocation and I
     
    119114{
    120115    RT_NOREF(pStreamVRDE, pCfgReq);
    121 
    122     if (pCfgAcq)
    123     {
    124         /*
    125          * Because of historical reasons the VRDP server operates on st_sample_t structures internally,
    126          * which is 2 * int64_t for left/right (stereo) channels.
    127          *
    128          * As the audio connector also uses this format, set the layout to "raw" and just let pass through
    129          * the data without any layout modification needed.
    130          */
    131         pCfgAcq->enmLayout = PDMAUDIOSTREAMLAYOUT_RAW;
    132 
    133         pCfgAcq->Props.uHz       = 22050; /* The VRDP server's internal frequency. */
    134         pCfgAcq->Props.cChannels = 2;
    135         pCfgAcq->Props.cbSample  = 2; /* 16 bit. */
    136         pCfgAcq->Props.fSigned   = true;
    137         pCfgAcq->Props.cShift    = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfgAcq->Props.cbSample, pCfgAcq->Props.cChannels);
    138 
    139         /* According to the VRDP docs, the VRDP server stores audio in 200ms chunks. */
    140         pCfgAcq->Backend.cFramesPeriod       = PDMAudioPropsMilliToFrames(&pCfgAcq->Props, 20  /*ms*/);
    141         pCfgAcq->Backend.cFramesBufferSize   = PDMAudioPropsMilliToFrames(&pCfgAcq->Props, 100 /*ms*/);
    142         pCfgAcq->Backend.cFramesPreBuffering = pCfgAcq->Backend.cFramesPeriod * 2;
    143     }
     116    AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER);
     117
     118    /*
     119     * The VRDP server does its own mixing and resampling because it may be
     120     * sending the audio to any number of different clients all with different
     121     * formats (including clients which hasn't yet connected).  So, it desires
     122     * the raw data from the mixer (somewhat akind to stereo signed 64-bit,
     123     * see st_sample_t and PDMAUDIOFRAME).
     124     */
     125    pCfgAcq->enmLayout = PDMAUDIOSTREAMLAYOUT_RAW;
     126    PDMAudioPropsInitEx(&pCfgAcq->Props, 8 /*64-bit*/, true /*fSigned*/, 2 /*stereo*/, 22050 /*Hz*/,
     127                        true /*fLittleEndian*/, true /*fRaw*/);
     128
     129    /* According to the VRDP docs, the VRDP server stores audio in 200ms chunks. */
     130    /** @todo r=bird: So, if VRDP does 200ms chunks, why do we report 100ms
     131     *        buffer and 20ms period?  How does these parameters at all correlate
     132     *        with the above comment?!? */
     133    pCfgAcq->Backend.cFramesPeriod       = PDMAudioPropsMilliToFrames(&pCfgAcq->Props, 20  /*ms*/);
     134    pCfgAcq->Backend.cFramesBufferSize   = PDMAudioPropsMilliToFrames(&pCfgAcq->Props, 100 /*ms*/);
     135    pCfgAcq->Backend.cFramesPreBuffering = pCfgAcq->Backend.cFramesPeriod * 2;
    144136
    145137    return VINF_SUCCESS;
     
    176168            rc = pDrv->pConsoleVRDPServer->SendAudioInputBegin(NULL, pStreamVRDE,
    177169                                                               PDMAudioPropsMilliToFrames(&pStreamVRDE->pCfg->Props, 200 /*ms*/),
    178                                                                pStreamVRDE->pCfg->Props.uHz, pStreamVRDE->pCfg->Props.cChannels,
    179                                                                pStreamVRDE->pCfg->Props.cbSample * 8 /* Bit */);
     170                                                               PDMAudioPropsHz(&pStreamVRDE->pCfg->Props),
     171                                                               PDMAudioPropsChannels(&pStreamVRDE->pCfg->Props),
     172                                                               PDMAudioPropsSampleBits(&pStreamVRDE->pCfg->Props));
    180173            if (rc == VERR_NOT_SUPPORTED)
    181174            {
     
    287280    /* Prepate the format. */
    288281    PPDMAUDIOPCMPROPS pProps = &pStreamVRDE->pCfg->Props;
    289     VRDEAUDIOFORMAT const VrdpFormat = VRDE_AUDIO_FMT_MAKE(pProps->uHz,
    290                                                            pProps->cChannels,
    291                                                            pProps->cbSample * 8 /* Bit */,
    292                                                            pProps->fSigned);
     282    VRDEAUDIOFORMAT const uVrdpFormat = VRDE_AUDIO_FMT_MAKE(PDMAudioPropsHz(pProps),
     283                                                            PDMAudioPropsChannels(pProps),
     284                                                            PDMAudioPropsSampleBits(pProps),
     285                                                            pProps->fSigned);
     286    Assert(uVrdpFormat == VRDE_AUDIO_FMT_MAKE(PDMAudioPropsHz(pProps), 2, 64, true));
    293287
    294288    /* We specified PDMAUDIOSTREAMLAYOUT_RAW (== S64), so
     
    314308        /* Note: The VRDP server expects int64_t samples per channel, regardless
    315309                 of the actual  sample bits (e.g 8 or 16 bits). */
    316         pDrv->pConsoleVRDPServer->SendAudioSamples(&paSampleBuf[cFramesWritten], cFramesChunk /* Frames */, VrdpFormat);
     310        pDrv->pConsoleVRDPServer->SendAudioSamples(&paSampleBuf[cFramesWritten], cFramesChunk /* Frames */, uVrdpFormat);
    317311
    318312        cFramesWritten += cFramesChunk;
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