VirtualBox

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


Ignore:
Timestamp:
Feb 6, 2017 2:13:36 PM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
113296
Message:

Audio: More abstraction for the backends: Now the backend stream's data is completely separate from the audio connector interface. That way the backends cannot mess with the audio connector's data (e.g. mixing buffers and friends) anymore, and those are forced to use the audio connector API as meant now. Needs more testing, partly work in progress.

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

Legend:

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

    r65596 r65624  
    6161} DRVAUDIOVRDE, *PDRVAUDIOVRDE;
    6262
    63 typedef struct VRDESTREAMIN
    64 {
    65     /** Note: Always must come first! */
    66     PDMAUDIOSTREAM       Stream;
    67     /** The PCM properties of this stream. */
    68     PDMAUDIOPCMPROPS     Props;
    69     /** Number of samples this stream can handle at once. */
    70     uint32_t             cSamplesMax;
    71     /** Circular buffer for holding the recorded audio samples from the host. */
    72     PRTCIRCBUF           pCircBuf;
    73 } VRDESTREAMIN, *PVRDESTREAMIN;
    74 
    75 typedef struct VRDESTREAMOUT
    76 {
    77     /** Note: Always must come first! */
    78     PDMAUDIOSTREAM       Stream;
    79     /** The PCM properties of this stream. */
    80     PDMAUDIOPCMPROPS     Props;
    81     uint64_t             old_ticks;
    82     uint64_t             cSamplesSentPerSec;
    83 } VRDESTREAMOUT, *PVRDESTREAMOUT;
    84 
    85 
    86 
    87 static int vrdeCreateStreamIn(PVRDESTREAMIN pStreamVRDE, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    88 {
    89     int rc = DrvAudioHlpStreamCfgToProps(pCfgReq, &pStreamVRDE->Props);
     63typedef struct VRDESTREAM
     64{
     65    /** The stream's acquired configuration. */
     66    PPDMAUDIOSTREAMCFG pCfg;
     67    union
     68    {
     69        struct
     70        {
     71            /** Number of samples this stream can handle at once. */
     72            uint32_t    cSamplesMax;
     73            /** Circular buffer for holding the recorded audio samples from the host. */
     74            PRTCIRCBUF  pCircBuf;
     75        } In;
     76        struct
     77        {
     78            uint64_t    old_ticks;
     79            uint64_t    cSamplesSentPerSec;
     80        } Out;
     81    };
     82} VRDESTREAM, *PVRDESTREAM;
     83
     84
     85static int vrdeCreateStreamIn(PVRDESTREAM pStreamVRDE, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
     86{
     87    pStreamVRDE->In.cSamplesMax = _1K; /** @todo Make this configurable. */
     88
     89    int rc = RTCircBufCreate(&pStreamVRDE->In.pCircBuf, pStreamVRDE->In.cSamplesMax * (pCfgReq->Props.cBits / 8) /* Bytes */);
    9090    if (RT_SUCCESS(rc))
    9191    {
    92         pStreamVRDE->cSamplesMax = _1K; /** @todo Make this configurable. */
    93 
    94         rc = RTCircBufCreate(&pStreamVRDE->pCircBuf, pStreamVRDE->cSamplesMax * (pStreamVRDE->Props.cBits / 8) /* Bytes */);
    95         if (RT_SUCCESS(rc))
    96         {
    97             if (pCfgAcq)
    98                 pCfgAcq->cSampleBufferSize = pStreamVRDE->cSamplesMax;
    99         }
     92        if (pCfgAcq)
     93            pCfgAcq->cSampleBufferHint = pStreamVRDE->In.cSamplesMax;
    10094    }
    10195
     
    10498
    10599
    106 static int vrdeCreateStreamOut(PVRDESTREAMOUT pStreamVRDE, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    107 {
    108     int rc = DrvAudioHlpStreamCfgToProps(pCfgReq, &pStreamVRDE->Props);
    109     if (RT_SUCCESS(rc))
    110     {
    111         if (pCfgAcq)
    112             pCfgAcq->cSampleBufferSize = _4K; /** @todo Make this configurable. */
    113     }
    114 
    115     return rc;
    116 }
    117 
    118 
    119 static int vrdeControlStreamOut(PDRVAUDIOVRDE pDrv, PVRDESTREAMOUT pStreamVRDE, PDMAUDIOSTREAMCMD enmStreamCmd)
     100static int vrdeCreateStreamOut(PVRDESTREAM pStreamVRDE, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
     101{
     102    RT_NOREF(pStreamVRDE, pCfgReq);
     103
     104    if (pCfgAcq)
     105        pCfgAcq->cSampleBufferHint = _4K; /** @todo Make this configurable. */
     106
     107    return VINF_SUCCESS;
     108}
     109
     110
     111static int vrdeControlStreamOut(PDRVAUDIOVRDE pDrv, PVRDESTREAM pStreamVRDE, PDMAUDIOSTREAMCMD enmStreamCmd)
    120112{
    121113    RT_NOREF(pDrv, pStreamVRDE, enmStreamCmd);
     
    127119
    128120
    129 static int vrdeControlStreamIn(PDRVAUDIOVRDE pDrv, PVRDESTREAMIN pVRDEStrmIn, PDMAUDIOSTREAMCMD enmStreamCmd)
     121static int vrdeControlStreamIn(PDRVAUDIOVRDE pDrv, PVRDESTREAM pStreamVRDE, PDMAUDIOSTREAMCMD enmStreamCmd)
    130122{
    131123    LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
     
    141133        case PDMAUDIOSTREAMCMD_ENABLE:
    142134        {
    143             rc = pDrv->pConsoleVRDPServer->SendAudioInputBegin(NULL, pVRDEStrmIn, pVRDEStrmIn->cSamplesMax,
    144                                                                pVRDEStrmIn->Props.uHz,
    145                                                                pVRDEStrmIn->Props.cChannels, pVRDEStrmIn->Props.cBits);
     135            rc = pDrv->pConsoleVRDPServer->SendAudioInputBegin(NULL, pStreamVRDE, pStreamVRDE->In.cSamplesMax,
     136                                                               pStreamVRDE->pCfg->Props.uHz, pStreamVRDE->pCfg->Props.cChannels,
     137                                                               pStreamVRDE->pCfg->Props.cBits);
    146138            if (rc == VERR_NOT_SUPPORTED)
    147139            {
     
    203195 */
    204196static DECLCALLBACK(int) drvAudioVRDEStreamCapture(PPDMIHOSTAUDIO pInterface,
    205                                                    PPDMAUDIOSTREAM pStream, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
     197                                                   PPDMAUDIOBACKENDSTREAM pStream, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
    206198{
    207199    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     
    211203    /* pcbRead is optional. */
    212204
    213     PVRDESTREAMIN pStreamVRDE = (PVRDESTREAMIN)pStream;
     205    PVRDESTREAM pStreamVRDE = (PVRDESTREAM)pStream;
    214206
    215207    size_t cbData = 0;
    216208
    217     if (RTCircBufUsed(pStreamVRDE->pCircBuf))
     209    if (RTCircBufUsed(pStreamVRDE->In.pCircBuf))
    218210    {
    219211        void *pvData;
    220212
    221         RTCircBufAcquireReadBlock(pStreamVRDE->pCircBuf, cbBuf, &pvData, &cbData);
     213        RTCircBufAcquireReadBlock(pStreamVRDE->In.pCircBuf, cbBuf, &pvData, &cbData);
    222214
    223215        if (cbData)
    224216            memcpy(pvBuf, pvData, cbData);
    225217
    226         RTCircBufReleaseReadBlock(pStreamVRDE->pCircBuf, cbData);
     218        RTCircBufReleaseReadBlock(pStreamVRDE->In.pCircBuf, cbData);
    227219    }
    228220
     
    237229 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamPlay}
    238230 */
    239 static DECLCALLBACK(int) drvAudioVRDEStreamPlay(PPDMIHOSTAUDIO pInterface,
    240                                                 PPDMAUDIOSTREAM pStream, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
     231static DECLCALLBACK(int) drvAudioVRDEStreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
     232                                                const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
    241233{
    242234    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     
    246238    /* pcbWritten is optional. */
    247239
    248     PDRVAUDIOVRDE  pDrv        = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
    249     PVRDESTREAMOUT pStreamVRDE = (PVRDESTREAMOUT)pStream;
     240    PDRVAUDIOVRDE pDrv        = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
     241    PVRDESTREAM   pStreamVRDE = (PVRDESTREAM)pStream;
    250242
    251243    uint32_t cbLive           = cbBuf;
    252244
    253245    uint64_t now              = PDMDrvHlpTMGetVirtualTime(pDrv->pDrvIns);
    254     uint64_t ticks            = now  - pStreamVRDE->old_ticks;
     246    uint64_t ticks            = now  - pStreamVRDE->Out.old_ticks;
    255247    uint64_t ticks_per_second = PDMDrvHlpTMGetVirtualFreq(pDrv->pDrvIns);
    256248
     249    PPDMAUDIOPCMPROPS pProps  = &pStreamVRDE->pCfg->Props;
     250
    257251    /* Minimize the rounding error: samples = int((ticks * freq) / ticks_per_second + 0.5). */
    258     uint32_t cbToWrite = (int)((2 * ticks * pStreamVRDE->Props.uHz + ticks_per_second) / ticks_per_second / 2);
     252    uint32_t cbToWrite = (int)((2 * ticks * pProps->uHz + ticks_per_second) / ticks_per_second / 2);
    259253
    260254    /* Remember when samples were consumed. */
    261     pStreamVRDE->old_ticks = now;
    262 
    263     VRDEAUDIOFORMAT format = VRDE_AUDIO_FMT_MAKE(pStreamVRDE->Props.uHz,
    264                                                  pStreamVRDE->Props.cChannels,
    265                                                  pStreamVRDE->Props.cBits,
    266                                                  pStreamVRDE->Props.fSigned);
     255    pStreamVRDE->Out.old_ticks = now;
     256
     257    VRDEAUDIOFORMAT format = VRDE_AUDIO_FMT_MAKE(pProps->uHz,
     258                                                 pProps->cChannels,
     259                                                 pProps->cBits,
     260                                                 pProps->fSigned);
    267261
    268262    Log2Func(("uFreq=%RU32, cChan=%RU8, cBits=%RU8, fSigned=%RTbool, enmFormat=%ld, cbLive=%RU32, cbToWrite=%RU32\n",
    269               pStreamVRDE->Props.uHz,   pStreamVRDE->Props.cChannels,
    270               pStreamVRDE->Props.cBits, pStreamVRDE->Props.fSigned,
    271               format, cbLive, cbToWrite));
     263              pProps->uHz,   pProps->cChannels, pProps->cBits, pProps->fSigned, format, cbLive, cbToWrite));
    272264
    273265    /* Don't play more than available. */
     
    291283
    292284        pDrv->pConsoleVRDPServer->SendAudioSamples((uint8_t *)pvBuf + cbWritten,
    293                                                    PDMAUDIOPCMPROPS_B2S(&pStreamVRDE->Props, cbChunk) /* Samples */, format);
     285                                                   PDMAUDIOSTREAMCFG_B2S(pStreamVRDE->pCfg, cbChunk) /* Samples */, format);
    294286        cbWritten += cbChunk;
    295287        Assert(cbWritten <= cbBuf);
     
    311303
    312304
    313 static int vrdeDestroyStreamIn(PDRVAUDIOVRDE pDrv, PVRDESTREAMIN pStreamVRDE)
     305static int vrdeDestroyStreamIn(PDRVAUDIOVRDE pDrv, PVRDESTREAM pStreamVRDE)
    314306{
    315307    if (pDrv->pConsoleVRDPServer)
    316308        pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL);
    317309
    318     if (pStreamVRDE->pCircBuf)
    319     {
    320         RTCircBufDestroy(pStreamVRDE->pCircBuf);
    321         pStreamVRDE->pCircBuf = NULL;
    322     }
    323 
    324     return VINF_SUCCESS;
    325 }
    326 
    327 
    328 static int vrdeDestroyStreamOut(PDRVAUDIOVRDE pDrv, PVRDESTREAMOUT pStreamVRDE)
     310    if (pStreamVRDE->In.pCircBuf)
     311    {
     312        RTCircBufDestroy(pStreamVRDE->In.pCircBuf);
     313        pStreamVRDE->In.pCircBuf = NULL;
     314    }
     315
     316    return VINF_SUCCESS;
     317}
     318
     319
     320static int vrdeDestroyStreamOut(PDRVAUDIOVRDE pDrv, PVRDESTREAM pStreamVRDE)
    329321{
    330322    RT_NOREF(pDrv, pStreamVRDE);
     
    339331static DECLCALLBACK(int) drvAudioVRDEGetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pBackendCfg)
    340332{
    341     NOREF(pInterface);
     333    RT_NOREF(pInterface);
    342334    AssertPtrReturn(pBackendCfg, VERR_INVALID_POINTER);
    343335
    344     pBackendCfg->cbStreamOut    = sizeof(VRDESTREAMOUT);
    345     pBackendCfg->cbStreamIn     = sizeof(VRDESTREAMIN);
     336    pBackendCfg->cbStreamOut    = sizeof(VRDESTREAM);
     337    pBackendCfg->cbStreamIn     = sizeof(VRDESTREAM);
    346338    pBackendCfg->cMaxStreamsIn  = UINT32_MAX;
    347339    pBackendCfg->cMaxStreamsOut = UINT32_MAX;
     
    379371 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
    380372 */
    381 static DECLCALLBACK(int) drvAudioVRDEStreamCreate(PPDMIHOSTAUDIO pInterface,
    382                                                   PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
     373static DECLCALLBACK(int) drvAudioVRDEStreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
     374                                                  PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    383375{
    384376    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     
    389381    RT_NOREF(pInterface);
    390382
     383    PVRDESTREAM pStreamVRDE = (PVRDESTREAM)pStream;
     384
    391385    int rc;
    392386    if (pCfgReq->enmDir == PDMAUDIODIR_IN)
    393     {
    394         PVRDESTREAMIN pStreamVRDE = (PVRDESTREAMIN)pStream;
    395         rc = vrdeCreateStreamIn(pStreamVRDE, pCfgReq, pCfgAcq);
    396     }
     387        rc = vrdeCreateStreamIn (pStreamVRDE, pCfgReq, pCfgAcq);
    397388    else
    398     {
    399         PVRDESTREAMOUT pStreamVRDE = (PVRDESTREAMOUT)pStream;
    400389        rc = vrdeCreateStreamOut(pStreamVRDE, pCfgReq, pCfgAcq);
     390
     391    if (RT_SUCCESS(rc))
     392    {
     393        pStreamVRDE->pCfg = DrvAudioHlpStreamCfgDup(pCfgAcq);
     394        if (!pStreamVRDE->pCfg)
     395            rc = VERR_NO_MEMORY;
    401396    }
    402397
     
    408403 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDestroy}
    409404 */
    410 static DECLCALLBACK(int) drvAudioVRDEStreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     405static DECLCALLBACK(int) drvAudioVRDEStreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     406{
     407    RT_NOREF(pInterface);
     408    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     409
     410    PDRVAUDIOVRDE pDrv        = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
     411    PVRDESTREAM   pStreamVRDE = (PVRDESTREAM)pStream;
     412
     413    if (!pStreamVRDE->pCfg) /* Not (yet) configured? Skip. */
     414        return VINF_SUCCESS;
     415
     416    int rc;
     417    if (pStreamVRDE->pCfg->enmDir == PDMAUDIODIR_IN)
     418        rc = vrdeDestroyStreamIn(pDrv, pStreamVRDE);
     419    else
     420        rc = vrdeDestroyStreamOut(pDrv, pStreamVRDE);
     421
     422    if (RT_SUCCESS(rc))
     423    {
     424        DrvAudioHlpStreamCfgFree(pStreamVRDE->pCfg);
     425        pStreamVRDE->pCfg = NULL;
     426    }
     427
     428    return rc;
     429}
     430
     431
     432/**
     433 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamControl}
     434 */
     435static DECLCALLBACK(int) drvAudioVRDEStreamControl(PPDMIHOSTAUDIO pInterface,
     436                                                   PPDMAUDIOBACKENDSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
    411437{
    412438    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    413439    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    414440
    415     PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
     441    PDRVAUDIOVRDE pDrv        = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
     442    PVRDESTREAM   pStreamVRDE = (PVRDESTREAM)pStream;
     443
     444    if (!pStreamVRDE->pCfg) /* Not (yet) configured? Skip. */
     445        return VINF_SUCCESS;
    416446
    417447    int rc;
    418     if (pStream->enmDir == PDMAUDIODIR_IN)
    419     {
    420         PVRDESTREAMIN pStreamVRDE = (PVRDESTREAMIN)pStream;
    421         rc = vrdeDestroyStreamIn(pDrv, pStreamVRDE);
    422     }
     448    if (pStreamVRDE->pCfg->enmDir == PDMAUDIODIR_IN)
     449        rc = vrdeControlStreamIn(pDrv, pStreamVRDE, enmStreamCmd);
    423450    else
    424     {
    425         PVRDESTREAMOUT pStreamVRDE = (PVRDESTREAMOUT)pStream;
    426         rc = vrdeDestroyStreamOut(pDrv, pStreamVRDE);
    427     }
     451        rc = vrdeControlStreamOut(pDrv, pStreamVRDE, enmStreamCmd);
    428452
    429453    return rc;
     
    432456
    433457/**
    434  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamControl}
    435  */
    436 static DECLCALLBACK(int) drvAudioVRDEStreamControl(PPDMIHOSTAUDIO pInterface,
    437                                                    PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
     458 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetStatus}
     459 */
     460static DECLCALLBACK(PDMAUDIOSTRMSTS) drvAudioVRDEStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     461{
     462    RT_NOREF(pInterface);
     463    RT_NOREF(pStream);
     464
     465    return (  PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED
     466            | PDMAUDIOSTRMSTS_FLAG_DATA_READABLE | PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE);
     467}
     468
     469
     470/**
     471 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamIterate}
     472 */
     473static DECLCALLBACK(int) drvAudioVRDEStreamIterate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
    438474{
    439475    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    440476    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    441 
    442     PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
    443 
    444     int rc;
    445     if (pStream->enmDir == PDMAUDIODIR_IN)
    446     {
    447         PVRDESTREAMIN pStreamVRDE = (PVRDESTREAMIN)pStream;
    448         rc = vrdeControlStreamIn(pDrv, pStreamVRDE, enmStreamCmd);
    449     }
    450     else
    451     {
    452         PVRDESTREAMOUT pStreamVRDE = (PVRDESTREAMOUT)pStream;
    453         rc = vrdeControlStreamOut(pDrv, pStreamVRDE, enmStreamCmd);
    454     }
    455 
    456     return rc;
    457 }
    458 
    459 
    460 /**
    461  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetStatus}
    462  */
    463 static DECLCALLBACK(PDMAUDIOSTRMSTS) drvAudioVRDEStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
    464 {
    465     NOREF(pInterface);
    466     NOREF(pStream);
    467 
    468     return (  PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED
    469             | PDMAUDIOSTRMSTS_FLAG_DATA_READABLE | PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE);
    470 }
    471 
    472 
    473 /**
    474  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamIterate}
    475  */
    476 static DECLCALLBACK(int) drvAudioVRDEStreamIterate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
    477 {
    478     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    479     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    480 
    481     LogFlowFuncEnter();
    482477
    483478    /* Nothing to do here for VRDE. */
     
    543538    AssertPtrReturn(pVRDEAudioBegin, VERR_INVALID_POINTER);
    544539
    545     PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pvContext;
     540    PVRDESTREAM pVRDEStrmIn = (PVRDESTREAM)pvContext;
    546541    AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER);
    547542
    548543    VRDEAUDIOFORMAT audioFmt = pVRDEAudioBegin->fmt;
    549544
    550     int iSampleHz  = VRDE_AUDIO_FMT_SAMPLE_FREQ(audioFmt);     NOREF(iSampleHz);
    551     int cChannels  = VRDE_AUDIO_FMT_CHANNELS(audioFmt);        NOREF(cChannels);
    552     int cBits      = VRDE_AUDIO_FMT_BITS_PER_SAMPLE(audioFmt); NOREF(cBits);
    553     bool fUnsigned = VRDE_AUDIO_FMT_SIGNED(audioFmt);          NOREF(fUnsigned);
     545    int iSampleHz  = VRDE_AUDIO_FMT_SAMPLE_FREQ(audioFmt);     RT_NOREF(iSampleHz);
     546    int cChannels  = VRDE_AUDIO_FMT_CHANNELS(audioFmt);        RT_NOREF(cChannels);
     547    int cBits      = VRDE_AUDIO_FMT_BITS_PER_SAMPLE(audioFmt); RT_NOREF(cBits);
     548    bool fUnsigned = VRDE_AUDIO_FMT_SIGNED(audioFmt);          RT_NOREF(fUnsigned);
    554549
    555550    LogFlowFunc(("cbSample=%RU32, iSampleHz=%d, cChannels=%d, cBits=%d, fUnsigned=%RTbool\n",
     
    562557int AudioVRDE::onVRDEInputData(void *pvContext, const void *pvData, uint32_t cbData)
    563558{
    564     PVRDESTREAMIN pStreamVRDE = (PVRDESTREAMIN)pvContext;
     559    PVRDESTREAM pStreamVRDE = (PVRDESTREAM)pvContext;
    565560    AssertPtrReturn(pStreamVRDE, VERR_INVALID_POINTER);
    566561
     
    568563    size_t cbBuf;
    569564
    570     RTCircBufAcquireWriteBlock(pStreamVRDE->pCircBuf, cbData, &pvBuf, &cbBuf);
     565    RTCircBufAcquireWriteBlock(pStreamVRDE->In.pCircBuf, cbData, &pvBuf, &cbBuf);
    571566
    572567    if (cbBuf)
    573568        memcpy(pvBuf, pvData, cbBuf);
    574569
    575     RTCircBufReleaseWriteBlock(pStreamVRDE->pCircBuf, cbBuf);
     570    RTCircBufReleaseWriteBlock(pStreamVRDE->In.pCircBuf, cbBuf);
    576571
    577572    if (cbBuf < cbData)
     
    584579int AudioVRDE::onVRDEInputEnd(void *pvContext)
    585580{
    586     NOREF(pvContext);
     581    RT_NOREF(pvContext);
    587582
    588583    return VINF_SUCCESS;
  • trunk/src/VBox/Main/src-client/DrvAudioVideoRec.cpp

    r65565 r65624  
    180180
    181181/**
    182  * Audio video recording output stream.
    183  */
    184 typedef struct AVRECSTREAMOUT
    185 {
    186     /** Note: Always must come first! */
    187     PDMAUDIOSTREAM       Stream;
    188     /** The PCM properties of this stream. */
    189     PDMAUDIOPCMPROPS     Props;
     182 * Audio video recording (output) stream.
     183 */
     184typedef struct AVRECSTREAM
     185{
     186    /** The stream's acquired configuration. */
     187    PPDMAUDIOSTREAMCFG   pCfg;
    190188    /** (Audio) frame buffer. */
    191189    PRTCIRCBUF           pCircBuf;
    192190    /** Pointer to sink to use for writing. */
    193191    PAVRECSINK           pSink;
    194 } AVRECSTREAMOUT, *PAVRECSTREAMOUT;
     192} AVRECSTREAM, *PAVRECSTREAM;
    195193
    196194/**
     
    359357 * @returns IPRT status code.
    360358 * @param   pThis               Driver instance.
    361  * @param   pStream             Audio output stream to create.
     359 * @param   pStreamAV           Audio output stream to create.
    362360 * @param   pSink               Recording sink to associate audio output stream to.
    363361 * @param   pCfgReq             Requested configuration by the audio backend.
    364362 * @param   pCfgAcq             Acquired configuration by the audio output stream.
    365363 */
    366 static int avRecCreateStreamOut(PDRVAUDIOVIDEOREC pThis, PPDMAUDIOSTREAM pStream,
     364static int avRecCreateStreamOut(PDRVAUDIOVIDEOREC pThis, PAVRECSTREAM pStreamAV,
    367365                                PAVRECSINK pSink, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    368366{
    369     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    370     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    371     AssertPtrReturn(pSink,   VERR_INVALID_POINTER);
    372     AssertPtrReturn(pCfgReq, VERR_INVALID_POINTER);
    373     AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER);
    374 
    375     PAVRECSTREAMOUT pStreamOut = (PAVRECSTREAMOUT)pStream;
     367    AssertPtrReturn(pThis,     VERR_INVALID_POINTER);
     368    AssertPtrReturn(pStreamAV, VERR_INVALID_POINTER);
     369    AssertPtrReturn(pSink,     VERR_INVALID_POINTER);
     370    AssertPtrReturn(pCfgReq,   VERR_INVALID_POINTER);
     371    AssertPtrReturn(pCfgAcq,   VERR_INVALID_POINTER);
    376372
    377373    if (pCfgReq->DestSource.Dest != PDMAUDIOPLAYBACKDEST_FRONT)
     
    380376
    381377        if (pCfgAcq)
    382             pCfgAcq->cSampleBufferSize = 0;
     378            pCfgAcq->cSampleBufferHint = 0;
    383379
    384380        LogRel2(("VideoRec: Support for surround audio not implemented yet\n"));
     
    386382    }
    387383
    388     int rc = DrvAudioHlpStreamCfgToProps(pCfgReq, &pStreamOut->Props);
    389     if (RT_FAILURE(rc))
    390         return rc;
     384    int rc = VINF_SUCCESS;
    391385
    392386#ifdef VBOX_WITH_LIBOPUS
     
    398392                                           WebMWriter::AudioCodec_Opus, WebMWriter::VideoCodec_None);
    399393        if (RT_SUCCESS(rc))
    400             rc = pSink->Con.WebM.pWebM->AddAudioTrack(pSink->Codec.Parms.uHz, pStreamOut->Props.cChannels, pStreamOut->Props.cBits,
     394            rc = pSink->Con.WebM.pWebM->AddAudioTrack(pSink->Codec.Parms.uHz, pCfgReq->Props.cChannels, pCfgReq->Props.cBits,
    401395                                                      &pSink->Con.WebM.uTrack);
    402396    }
     
    405399        return rc;
    406400
    407     rc = RTCircBufCreate(&pStreamOut->pCircBuf, (pSink->Codec.Opus.csFrame * pSink->Codec.Parms.cChannels) * sizeof(uint16_t));
     401    rc = RTCircBufCreate(&pStreamAV->pCircBuf, (pSink->Codec.Opus.csFrame * pSink->Codec.Parms.cChannels) * sizeof(uint16_t));
    408402    if (RT_SUCCESS(rc))
    409403    {
    410         pStreamOut->pSink = pSink; /* Assign sink to stream. */
     404        pStreamAV->pSink = pSink; /* Assign sink to stream. */
    411405
    412406        if (pCfgAcq)
     
    414408            /* Make sure to let the driver backend know that we need the audio data in
    415409             * a specific sampling rate Opus is optimized for. */
    416             pCfgAcq->uHz               = pSink->Codec.Parms.uHz;
    417             pCfgAcq->cSampleBufferSize = _4K; /** @todo Make this configurable. */
     410            pCfgAcq->Props.uHz         = pSink->Codec.Parms.uHz;
     411            pCfgAcq->Props.cShift      = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfgAcq->Props.cBits, pCfgAcq->Props.cChannels);
     412            pCfgAcq->cSampleBufferHint = _4K; /** @todo Make this configurable. */
    418413        }
    419414    }
    420415#else
    421     RT_NOREF(pThis, pSink, pStream, pCfgReq, pCfgAcq);
     416    RT_NOREF(pThis, pSink, pStreamAV, pCfgReq, pCfgAcq);
    422417    rc = VERR_NOT_SUPPORTED;
    423418#endif /* VBOX_WITH_LIBOPUS */
     
    433428 * @returns IPRT status code.
    434429 * @param   pThis               Driver instance.
    435  * @param   pStream             Audio output stream to destroy.
    436  */
    437 static int avRecDestroyStreamOut(PDRVAUDIOVIDEOREC pThis, PPDMAUDIOSTREAM pStream)
     430 * @param   pStreamAV           Audio output stream to destroy.
     431 */
     432static int avRecDestroyStreamOut(PDRVAUDIOVIDEOREC pThis, PAVRECSTREAM pStreamAV)
    438433{
    439434    RT_NOREF(pThis);
    440     PAVRECSTREAMOUT pStreamOut = (PAVRECSTREAMOUT)pStream;
    441 
    442     if (pStreamOut->pCircBuf)
    443     {
    444         RTCircBufDestroy(pStreamOut->pCircBuf);
    445         pStreamOut->pCircBuf = NULL;
     435
     436    if (pStreamAV->pCircBuf)
     437    {
     438        RTCircBufDestroy(pStreamAV->pCircBuf);
     439        pStreamAV->pCircBuf = NULL;
    446440    }
    447441
     
    455449 * @returns IPRT status code.
    456450 * @param   pThis               Driver instance.
    457  * @param   pStream             Audio output stream to control.
     451 * @param   pStreamAV           Audio output stream to control.
    458452 * @param   enmStreamCmd        Stream command to issue.
    459453 */
    460454static int avRecControlStreamOut(PDRVAUDIOVIDEOREC pThis,
    461                                  PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
    462 {
    463     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    464     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    465     RT_NOREF(enmStreamCmd);
    466 
    467     RT_NOREF(pThis);
    468 
    469     LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
     455                                 PAVRECSTREAM pStreamAV, PDMAUDIOSTREAMCMD enmStreamCmd)
     456{
     457    RT_NOREF(pThis, pStreamAV);
    470458
    471459    switch (enmStreamCmd)
     
    520508 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCapture}
    521509 */
    522 static DECLCALLBACK(int) drvAudioVideoRecStreamCapture(PPDMIHOSTAUDIO pInterface,
    523                                                        PPDMAUDIOSTREAM pStream, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
     510static DECLCALLBACK(int) drvAudioVideoRecStreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
     511                                                       void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
    524512{
    525513    RT_NOREF(pInterface, pStream, pvBuf, cbBuf);
     
    535523 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamPlay}
    536524 */
    537 static DECLCALLBACK(int) drvAudioVideoRecStreamPlay(PPDMIHOSTAUDIO pInterface,
    538                                                     PPDMAUDIOSTREAM pStream, const void *pvBuf, uint32_t cbBuf,
    539                                                     uint32_t *pcbWritten)
     525static DECLCALLBACK(int) drvAudioVideoRecStreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
     526                                                    const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
    540527{
    541528    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     
    545532    /* pcbWritten is optional. */
    546533
    547     PDRVAUDIOVIDEOREC pThis      = PDMIHOSTAUDIO_2_DRVAUDIOVIDEOREC(pInterface);
     534    PDRVAUDIOVIDEOREC pThis     = PDMIHOSTAUDIO_2_DRVAUDIOVIDEOREC(pInterface);
    548535    RT_NOREF(pThis);
    549     PAVRECSTREAMOUT   pStreamOut = (PAVRECSTREAMOUT)pStream;
     536    PAVRECSTREAM      pStreamAV = (PAVRECSTREAM)pStream;
    550537
    551538    int rc = VINF_SUCCESS;
     
    557544     */
    558545#ifdef VBOX_WITH_LIBOPUS
    559     PAVRECSINK pSink    = pStreamOut->pSink;
     546    PAVRECSINK pSink    = pStreamAV->pSink;
    560547    AssertPtr(pSink);
    561     PRTCIRCBUF pCircBuf = pStreamOut->pCircBuf;
     548    PRTCIRCBUF pCircBuf = pStreamAV->pCircBuf;
    562549    AssertPtr(pCircBuf);
    563550
     
    598585
    599586    const uint32_t csFrame = pSink->Codec.Opus.csFrame;
    600     const uint32_t cbFrame = PDMAUDIOPCMPROPS_S2B(&pStreamOut->Props, csFrame);
     587    const uint32_t cbFrame = PDMAUDIOSTREAMCFG_S2B(pStreamAV->pCfg, csFrame);
    601588
    602589    while (RTCircBufUsed(pCircBuf) >= cbFrame)
     
    716703static DECLCALLBACK(int) drvAudioVideoRecGetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pBackendCfg)
    717704{
    718     NOREF(pInterface);
     705    RT_NOREF(pInterface);
    719706    AssertPtrReturn(pBackendCfg, VERR_INVALID_POINTER);
    720707
    721     pBackendCfg->cbStreamOut    = sizeof(AVRECSTREAMOUT);
     708    pBackendCfg->cbStreamOut    = sizeof(AVRECSTREAM);
    722709    pBackendCfg->cbStreamIn     = 0;
    723710    pBackendCfg->cMaxStreamsIn  = 0;
     
    756743 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
    757744 */
    758 static DECLCALLBACK(int) drvAudioVideoRecStreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     745static DECLCALLBACK(int) drvAudioVideoRecStreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
    759746                                                      PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    760747{
    761748    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    762     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    763749    AssertPtrReturn(pCfgReq,    VERR_INVALID_POINTER);
    764750    AssertPtrReturn(pCfgAcq,    VERR_INVALID_POINTER);
    765751
    766     PDRVAUDIOVIDEOREC pThis = PDMIHOSTAUDIO_2_DRVAUDIOVIDEOREC(pInterface);
     752    if (pCfgReq->enmDir == PDMAUDIODIR_IN)
     753        return VERR_NOT_SUPPORTED;
     754
     755    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     756
     757    PDRVAUDIOVIDEOREC pThis     = PDMIHOSTAUDIO_2_DRVAUDIOVIDEOREC(pInterface);
     758    PAVRECSTREAM      pStreamAV = (PAVRECSTREAM)pStream;
    767759
    768760    /* For now we only have one sink, namely the driver's one.
     
    770762    PAVRECSINK pSink = &pThis->Sink;
    771763
    772     if (pCfgReq->enmDir == PDMAUDIODIR_OUT)
    773         return avRecCreateStreamOut(pThis, pStream, pSink, pCfgReq, pCfgAcq);
    774 
    775     return VERR_NOT_SUPPORTED;
     764    int rc = avRecCreateStreamOut(pThis, pStreamAV, pSink, pCfgReq, pCfgAcq);
     765    if (RT_SUCCESS(rc))
     766    {
     767        pStreamAV->pCfg = DrvAudioHlpStreamCfgDup(pCfgAcq);
     768        if (!pStreamAV->pCfg)
     769            rc = VERR_NO_MEMORY;
     770    }
     771
     772    return rc;
    776773}
    777774
     
    780777 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDestroy}
    781778 */
    782 static DECLCALLBACK(int) drvAudioVideoRecStreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     779static DECLCALLBACK(int) drvAudioVideoRecStreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
    783780{
    784781    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    785782    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    786783
    787     PDRVAUDIOVIDEOREC pThis = PDMIHOSTAUDIO_2_DRVAUDIOVIDEOREC(pInterface);
    788 
    789     if (pStream->enmDir == PDMAUDIODIR_OUT)
    790         return avRecDestroyStreamOut(pThis, pStream);
    791 
    792     return VINF_SUCCESS;
     784    PDRVAUDIOVIDEOREC pThis     = PDMIHOSTAUDIO_2_DRVAUDIOVIDEOREC(pInterface);
     785    PAVRECSTREAM      pStreamAV = (PAVRECSTREAM)pStream;
     786
     787    if (!pStreamAV->pCfg) /* Not (yet) configured? Skip. */
     788        return VINF_SUCCESS;
     789
     790    int rc = VINF_SUCCESS;
     791
     792    if (pStreamAV->pCfg->enmDir == PDMAUDIODIR_OUT)
     793        rc = avRecDestroyStreamOut(pThis, pStreamAV);
     794
     795    if (RT_SUCCESS(rc))
     796    {
     797        DrvAudioHlpStreamCfgFree(pStreamAV->pCfg);
     798        pStreamAV->pCfg = NULL;
     799    }
     800
     801    return rc;
    793802}
    794803
     
    798807 */
    799808static DECLCALLBACK(int) drvAudioVideoRecStreamControl(PPDMIHOSTAUDIO pInterface,
    800                                                        PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
     809                                                       PPDMAUDIOBACKENDSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
    801810{
    802811    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    803812    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    804813
    805     PDRVAUDIOVIDEOREC pThis = PDMIHOSTAUDIO_2_DRVAUDIOVIDEOREC(pInterface);
    806 
    807     Assert(pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST);
    808 
    809     if (pStream->enmDir == PDMAUDIODIR_OUT)
    810         return avRecControlStreamOut(pThis,  pStream, enmStreamCmd);
     814    PDRVAUDIOVIDEOREC pThis     = PDMIHOSTAUDIO_2_DRVAUDIOVIDEOREC(pInterface);
     815    PAVRECSTREAM      pStreamAV = (PAVRECSTREAM)pStream;
     816
     817    if (!pStreamAV->pCfg) /* Not (yet) configured? Skip. */
     818        return VINF_SUCCESS;
     819
     820    if (pStreamAV->pCfg->enmDir == PDMAUDIODIR_OUT)
     821        return avRecControlStreamOut(pThis, pStreamAV, enmStreamCmd);
    811822
    812823    return VINF_SUCCESS;
     
    817828 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetStatus}
    818829 */
    819 static DECLCALLBACK(PDMAUDIOSTRMSTS) drvAudioVideoRecStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
    820 {
    821     NOREF(pInterface);
    822     NOREF(pStream);
     830static DECLCALLBACK(PDMAUDIOSTRMSTS) drvAudioVideoRecStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     831{
     832    RT_NOREF(pInterface);
     833    RT_NOREF(pStream);
    823834
    824835    return (  PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED
     
    830841 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamIterate}
    831842 */
    832 static DECLCALLBACK(int) drvAudioVideoRecStreamIterate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     843static DECLCALLBACK(int) drvAudioVideoRecStreamIterate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
    833844{
    834845    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
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