VirtualBox

Changeset 88288 in vbox


Ignore:
Timestamp:
Mar 25, 2021 11:00:38 AM (4 years ago)
Author:
vboxsync
Message:

DrvHostAudioOss: Kicked out the unused mmap code and the unnecessary buffer we allocated when mmap failed or wasn't used. Simplified the StreamCapture code a little as well as output stream opening code. bugref:9890

File:
1 edited

Legend:

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

    r88287 r88288  
    8383    /** Buffer alignment. */
    8484    uint8_t            uAlign;
    85     union
    86     {
    87         struct
    88         {
    89 
    90         } In;
    91         struct
    92         {
    93 #ifndef RT_OS_L4
    94             /** Whether we use a memory mapped file instead of our
    95              *  own allocated PCM buffer below. */
    96             /** @todo The memory mapped code seems to be utterly broken.
    97              *        Needs investigation! */
    98             bool       fMMIO;
    99 #endif
    100         } Out;
    101     };
    10285    int                hFile;
    10386    int                cFragments;
    10487    int                cbFragmentSize;
    105     /** Own PCM buffer. */
    106     void              *pvBuf;
    107     /** Size (in bytes) of own PCM buffer. */
    108     size_t             cbBuf;
    10988    int                old_optr;
    11089} OSSAUDIOSTREAM, *POSSAUDIOSTREAM;
     
    11291typedef struct OSSAUDIOCFG
    11392{
    114 #ifndef RT_OS_L4
    115     bool try_mmap;
    116 #endif
    11793    int nfrags;
    11894    int fragsize;
     
    124100static OSSAUDIOCFG s_OSSConf =
    125101{
    126 #ifndef RT_OS_L4
    127     false,
    128 #endif
    129102    4,
    130103    4096,
     
    339312        case PDMAUDIOSTREAMCMD_RESUME:
    340313        {
    341             PDMAudioPropsClearBuffer(&pStreamOSS->pCfg->Props, pStreamOSS->pvBuf, pStreamOSS->cbBuf,
    342                                      PDMAUDIOPCMPROPS_B2F(&pStreamOSS->pCfg->Props, pStreamOSS->cbBuf));
    343 
    344314            int mask = PCM_ENABLE_OUTPUT;
    345315            if (ioctl(pStreamOSS->hFile, SNDCTL_DSP_SETTRIGGER, &mask) < 0)
     
    391361                                                         void *pvBuf, uint32_t uBufSize, uint32_t *puRead)
    392362{
     363    POSSAUDIOSTREAM pStreamOSS = (POSSAUDIOSTREAM)pStream;
     364    AssertPtrReturn(pStreamOSS, VERR_INVALID_POINTER);
    393365    RT_NOREF(pInterface);
    394     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    395 
    396     POSSAUDIOSTREAM pStreamOSS = (POSSAUDIOSTREAM)pStream;
    397 
    398     int rc = VINF_SUCCESS;
    399 
    400     size_t cbToRead = RT_MIN(pStreamOSS->cbBuf, uBufSize);
    401 
     366
     367
     368    size_t cbToRead = uBufSize;
    402369    LogFlowFunc(("cbToRead=%zi\n", cbToRead));
    403370
    404     uint32_t cbReadTotal = 0;
    405     uint32_t cbTemp;
    406     ssize_t  cbRead;
    407     size_t   offWrite = 0;
    408 
    409     while (cbToRead)
    410     {
    411         cbTemp = RT_MIN(cbToRead, pStreamOSS->cbBuf);
    412         AssertBreakStmt(cbTemp, rc = VERR_NO_DATA);
    413         cbRead = read(pStreamOSS->hFile, (uint8_t *)pStreamOSS->pvBuf, cbTemp);
    414 
    415         LogFlowFunc(("cbRead=%zi, cbTemp=%RU32, cbToRead=%zu\n", cbRead, cbTemp, cbToRead));
    416 
    417         if (cbRead < 0)
    418         {
    419             switch (errno)
    420             {
    421                 case 0:
    422                 {
    423                     LogFunc(("Failed to read %z frames\n", cbRead));
    424                     rc = VERR_ACCESS_DENIED;
    425                     break;
    426                 }
    427 
    428                 case EINTR:
    429                 case EAGAIN:
    430                     rc = VERR_NO_DATA;
    431                     break;
    432 
    433                 default:
    434                     LogFlowFunc(("Failed to read %zu input frames, rc=%Rrc\n", cbTemp, rc));
    435                     rc = VERR_GENERAL_FAILURE; /** @todo Fix this. */
    436                     break;
    437             }
    438 
    439             if (RT_FAILURE(rc))
    440                 break;
    441         }
    442         else if (cbRead)
    443         {
    444             memcpy((uint8_t *)pvBuf + offWrite, pStreamOSS->pvBuf, cbRead);
    445 
     371    uint8_t * const pbDst    = (uint8_t *)pvBuf;
     372    size_t          offWrite = 0;
     373    while (cbToRead > 0)
     374    {
     375        ssize_t cbRead = read(pStreamOSS->hFile, &pbDst[offWrite], cbToRead);
     376        if (cbRead)
     377        {
     378            LogFlowFunc(("cbRead=%zi, offWrite=%zu cbToRead=%zu\n", cbRead, offWrite, cbToRead));
    446379            Assert((ssize_t)cbToRead >= cbRead);
    447380            cbToRead    -= cbRead;
    448381            offWrite    += cbRead;
    449             cbReadTotal += cbRead;
    450         }
    451         else /* No more data, try next round. */
    452             break;
    453     }
    454 
    455     if (rc == VERR_NO_DATA)
    456         rc = VINF_SUCCESS;
    457 
    458     if (RT_SUCCESS(rc))
    459     {
    460         if (puRead)
    461             *puRead = cbReadTotal;
    462     }
    463 
    464     return rc;
     382        }
     383        else
     384        {
     385            LogFunc(("cbRead=%zi, offWrite=%zu cbToRead=%zu errno=%d\n", cbRead, offWrite, cbToRead, errno));
     386
     387            /* Don't complain about errors if we've retrieved some audio data already.  */
     388            if (cbRead < 0 && offWrite == 0 && errno != EINTR && errno != EAGAIN)
     389            {
     390                AssertStmt(errno != 0, errno = EACCES);
     391                int rc = RTErrConvertFromErrno(errno);
     392                LogFunc(("Failed to read %zu input frames, errno=%d rc=%Rrc\n", cbToRead, errno, rc));
     393                return rc;
     394            }
     395            break;
     396        }
     397    }
     398
     399    if (puRead)
     400        *puRead = offWrite;
     401    return VINF_SUCCESS;
    465402}
    466403
     
    472409    LogFlowFuncEnter();
    473410
    474     if (pStreamOSS->pvBuf)
    475     {
    476         Assert(pStreamOSS->cbBuf);
    477 
    478         RTMemFree(pStreamOSS->pvBuf);
    479         pStreamOSS->pvBuf = NULL;
    480     }
    481 
    482     pStreamOSS->cbBuf = 0;
    483 
    484411    ossStreamClose(&pStreamOSS->hFile);
    485412
     
    491418{
    492419    POSSAUDIOSTREAM pStreamOSS = (POSSAUDIOSTREAM)pStream;
    493 
    494 #ifndef RT_OS_L4
    495     if (pStreamOSS->Out.fMMIO)
    496     {
    497         if (pStreamOSS->pvBuf)
    498         {
    499             Assert(pStreamOSS->cbBuf);
    500 
    501             int rc2 = munmap(pStreamOSS->pvBuf, pStreamOSS->cbBuf);
    502             if (rc2 == 0)
    503             {
    504                 pStreamOSS->pvBuf      = NULL;
    505                 pStreamOSS->cbBuf      = 0;
    506 
    507                 pStreamOSS->Out.fMMIO  = false;
    508             }
    509             else
    510                 LogRel(("OSS: Failed to memory unmap playback buffer on close: %s\n", strerror(errno)));
    511         }
    512     }
    513     else
    514 #endif
    515     {
    516         if (pStreamOSS->pvBuf)
    517         {
    518             Assert(pStreamOSS->cbBuf);
    519 
    520             RTMemFree(pStreamOSS->pvBuf);
    521             pStreamOSS->pvBuf = NULL;
    522         }
    523 
    524         pStreamOSS->cbBuf = 0;
    525     }
    526420
    527421    ossStreamClose(&pStreamOSS->hFile);
     
    632526            if (RT_SUCCESS(rc))
    633527            {
    634                 size_t cbBuf = PDMAUDIOSTREAMCFG_F2B(pCfgAcq, ossAcq.cFragments * ossAcq.cbFragmentSize);
    635                 void  *pvBuf = RTMemAlloc(cbBuf);
    636                 if (!pvBuf)
    637                 {
    638                     LogRel(("OSS: Failed allocating capturing buffer with (%zu bytes)\n", cbBuf));
    639                     rc = VERR_NO_MEMORY;
    640                 }
    641 
    642528                pStreamOSS->hFile = hFile;
    643                 pStreamOSS->pvBuf = pvBuf;
    644                 pStreamOSS->cbBuf = cbBuf;
    645529
    646530                pCfgAcq->Backend.cFramesPeriod     = PDMAUDIOSTREAMCFG_B2F(pCfgAcq, ossAcq.cbFragmentSize);
     
    662546static int ossCreateStreamOut(POSSAUDIOSTREAM pStreamOSS, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    663547{
    664     int rc;
     548    OSSAUDIOSTREAMCFG reqStream;
     549    RT_ZERO(reqStream);
     550
     551    memcpy(&reqStream.Props, &pCfgReq->Props, sizeof(PDMAUDIOPCMPROPS));
     552    reqStream.cFragments     = s_OSSConf.nfrags;
     553    reqStream.cbFragmentSize = s_OSSConf.fragsize;
     554
     555    OSSAUDIOSTREAMCFG obtStream;
     556    RT_ZERO(obtStream);
     557
    665558    int hFile = -1;
    666 
    667     do
    668     {
    669         OSSAUDIOSTREAMCFG reqStream;
    670         RT_ZERO(reqStream);
    671 
    672         OSSAUDIOSTREAMCFG obtStream;
    673         RT_ZERO(obtStream);
    674 
    675         memcpy(&reqStream.Props, &pCfgReq->Props, sizeof(PDMAUDIOPCMPROPS));
    676 
    677         reqStream.cFragments     = s_OSSConf.nfrags;
    678         reqStream.cbFragmentSize = s_OSSConf.fragsize;
    679 
    680         rc = ossStreamOpen(s_OSSConf.devpath_out, O_WRONLY, &reqStream, &obtStream, &hFile);
    681         if (RT_SUCCESS(rc))
    682         {
    683             memcpy(&pCfgAcq->Props, &obtStream.Props, sizeof(PDMAUDIOPCMPROPS));
    684 
    685             if (obtStream.cFragments * obtStream.cbFragmentSize & pStreamOSS->uAlign)
    686             {
    687                 LogRel(("OSS: Warning: Misaligned playback buffer: Size = %zu, Alignment = %u\n",
    688                         obtStream.cFragments * obtStream.cbFragmentSize, pStreamOSS->uAlign + 1));
    689             }
    690         }
    691 
    692         if (RT_SUCCESS(rc)) /** @todo r=bird: great code structure ... */
    693         {
    694             pStreamOSS->Out.fMMIO = false;
    695 
    696             size_t cbBuf = PDMAUDIOSTREAMCFG_F2B(pCfgAcq, obtStream.cFragments * obtStream.cbFragmentSize);
    697             Assert(cbBuf);
    698 
    699 #ifndef RT_OS_L4
    700             if (s_OSSConf.try_mmap)
    701             {
    702                 pStreamOSS->pvBuf = mmap(0, cbBuf, PROT_READ | PROT_WRITE, MAP_SHARED, hFile, 0);
    703                 if (pStreamOSS->pvBuf == MAP_FAILED)
    704                 {
    705                     LogRel(("OSS: Failed to memory map %zu bytes of playback buffer: %s\n", cbBuf, strerror(errno)));
    706                     rc = RTErrConvertFromErrno(errno);
    707                     break;
    708                 }
    709                 else
    710                 {
    711                     int mask = 0;
    712                     if (ioctl(hFile, SNDCTL_DSP_SETTRIGGER, &mask) < 0)
    713                     {
    714                         LogRel(("OSS: Failed to retrieve initial trigger mask for playback buffer: %s\n", strerror(errno)));
    715                         rc = RTErrConvertFromErrno(errno);
    716                         /* Note: No break here, need to unmap file first! */
    717                     }
    718                     else
    719                     {
    720                         mask = PCM_ENABLE_OUTPUT;
    721                         if (ioctl (hFile, SNDCTL_DSP_SETTRIGGER, &mask) < 0)
    722                         {
    723                             LogRel(("OSS: Failed to retrieve PCM_ENABLE_OUTPUT mask: %s\n", strerror(errno)));
    724                             rc = RTErrConvertFromErrno(errno);
    725                             /* Note: No break here, need to unmap file first! */
    726                         }
    727                         else
    728                         {
    729                             pStreamOSS->Out.fMMIO = true;
    730                             LogRel(("OSS: Using MMIO\n"));
    731                         }
    732                     }
    733 
    734                     if (RT_FAILURE(rc))
    735                     {
    736                         int rc2 = munmap(pStreamOSS->pvBuf, cbBuf);
    737                         if (rc2)
    738                             LogRel(("OSS: Failed to memory unmap playback buffer: %s\n", strerror(errno)));
    739                         break;
    740                     }
    741                 }
    742             }
    743 #endif /* !RT_OS_L4 */
    744 
    745             /* Memory mapping failed above? Try allocating an own buffer. */
    746 #ifndef RT_OS_L4
    747             if (!pStreamOSS->Out.fMMIO)
    748             {
    749 #endif
    750                 void *pvBuf = RTMemAlloc(cbBuf);
    751                 if (!pvBuf)
    752                 {
    753                     LogRel(("OSS: Failed allocating playback buffer with %zu bytes\n", cbBuf));
    754                     rc = VERR_NO_MEMORY;
    755                     break;
    756                 }
    757 
    758                 pStreamOSS->hFile = hFile;
    759                 pStreamOSS->pvBuf = pvBuf;
    760                 pStreamOSS->cbBuf = cbBuf;
    761 #ifndef RT_OS_L4
    762             }
    763 #endif
    764             pCfgAcq->Backend.cFramesPeriod     = PDMAUDIOSTREAMCFG_B2F(pCfgAcq, obtStream.cbFragmentSize);
    765             pCfgAcq->Backend.cFramesBufferSize = pCfgAcq->Backend.cFramesPeriod * 2; /* Use "double buffering" */
    766         }
    767 
    768     } while (0);
    769 
    770     if (RT_FAILURE(rc))
    771         ossStreamClose(&hFile);
     559    int rc = ossStreamOpen(s_OSSConf.devpath_out, O_WRONLY, &reqStream, &obtStream, &hFile);
     560    if (RT_SUCCESS(rc))
     561    {
     562        memcpy(&pCfgAcq->Props, &obtStream.Props, sizeof(PDMAUDIOPCMPROPS));
     563
     564        if ((obtStream.cFragments * obtStream.cbFragmentSize) & pStreamOSS->uAlign)
     565            LogRel(("OSS: Warning: Misaligned playback buffer: Size = %zu, Alignment = %u\n",
     566                    obtStream.cFragments * obtStream.cbFragmentSize, pStreamOSS->uAlign + 1));
     567
     568        pStreamOSS->hFile = hFile;
     569
     570        pCfgAcq->Backend.cFramesPeriod     = PDMAUDIOSTREAMCFG_B2F(pCfgAcq, obtStream.cbFragmentSize);
     571        pCfgAcq->Backend.cFramesBufferSize = pCfgAcq->Backend.cFramesPeriod * 2; /* Use "double buffering" */
     572
     573    }
    772574
    773575    LogFlowFuncLeaveRC(rc);
     
    790592     */
    791593    uint32_t cbToWrite;
    792 #ifndef RT_OS_L4
    793     count_info CountInfo = {0,0,0};
    794     if (pStreamOSS->Out.fMMIO)
    795     {
    796         /* Get current playback pointer. */
    797         int rc2 = ioctl(pStreamOSS->hFile, SNDCTL_DSP_GETOPTR, &CountInfo);
    798         AssertLogRelMsgReturn(rc2 >= 0, ("OSS: Failed to retrieve current playback pointer: %s (%d)\n", strerror(errno), errno),
    799                               RTErrConvertFromErrno(errno));
    800 
    801         int cbData;
    802         if (CountInfo.ptr >= pStreamOSS->old_optr)
    803             cbData = CountInfo.ptr - pStreamOSS->old_optr;
    804         else
    805             cbData = pStreamOSS->cbBuf + CountInfo.ptr - pStreamOSS->old_optr;
    806         Assert(cbData >= 0);
    807         cbToWrite = (unsigned)cbData;
    808     }
    809     else
     594    audio_buf_info abinfo;
     595    int rc2 = ioctl(pStreamOSS->hFile, SNDCTL_DSP_GETOSPACE, &abinfo);
     596    AssertLogRelMsgReturn(rc2 >= 0, ("OSS: Failed to retrieve current playback buffer: %s (%d)\n", strerror(errno), errno),
     597                          RTErrConvertFromErrno(errno));
     598
     599#if 0   /** @todo r=bird: WTF do we make a fuss over abinfo.bytes for when we don't even use it?!? */
     600    AssertLogRelMsgReturn(abinfo.bytes >= 0, ("OSS: Warning: Invalid available size: %d\n", abinfo.bytes), VERR_INTERNAL_ERROR_3);
     601    if ((unsigned)abinfo.bytes > cbBuf)
     602    {
     603        LogRel2(("OSS: Warning: Too big output size (%d > %RU32), limiting to %RU32\n", abinfo.bytes, cbBuf, cbBuf));
     604        abinfo.bytes = cbBuf;
     605        /* Keep going. */
     606    }
    810607#endif
    811     {
    812         audio_buf_info abinfo;
    813         int rc2 = ioctl(pStreamOSS->hFile, SNDCTL_DSP_GETOSPACE, &abinfo);
    814         AssertLogRelMsgReturn(rc2 >= 0, ("OSS: Failed to retrieve current playback buffer: %s (%d)\n", strerror(errno), errno),
    815                               RTErrConvertFromErrno(errno));
    816 
    817 #if 0   /** @todo r=bird: WTF do we make a fuss over abinfo.bytes for when we don't even use it?!? */
    818         AssertLogRelMsgReturn(abinfo.bytes >= 0, ("OSS: Warning: Invalid available size: %d\n", abinfo.bytes), VERR_INTERNAL_ERROR_3);
    819         if ((unsigned)abinfo.bytes > cbBuf)
    820         {
    821             LogRel2(("OSS: Warning: Too big output size (%d > %RU32), limiting to %RU32\n", abinfo.bytes, cbBuf, cbBuf));
    822             abinfo.bytes = cbBuf;
    823             /* Keep going. */
    824         }
    825 #endif
    826         cbToWrite = (unsigned)(abinfo.fragments * abinfo.fragsize);
    827     }
     608    cbToWrite = (unsigned)(abinfo.fragments * abinfo.fragsize);
    828609    cbToWrite = RT_MIN(cbToWrite, cbBuf);
    829     cbToWrite = RT_MIN(cbToWrite, pStreamOSS->cbBuf);
    830 
    831     /*
    832      * This is probably for the mmap functionality and not needed in the no-mmap case.
    833      */
    834     /** @todo skip for non-mmap?   */
    835     uint8_t *pbBuf = (uint8_t *)memcpy(pStreamOSS->pvBuf, pvBuf, cbToWrite);
    836610
    837611    /*
    838612     * Write.
    839613     */
    840     uint32_t cbChunk  = cbToWrite;
    841     uint32_t offChunk = 0;
     614    uint8_t const *pbBuf    = (uint8_t const *)pvBuf;
     615    uint32_t       cbChunk  = cbToWrite;
     616    uint32_t       offChunk = 0;
    842617    while (cbChunk > 0)
    843618    {
     
    858633        }
    859634    }
    860 
    861 #ifndef RT_OS_L4
    862     /* Update read pointer. */
    863     if (pStreamOSS->Out.fMMIO)
    864         pStreamOSS->old_optr = CountInfo.ptr;
    865 #endif
    866635
    867636    *pcbWritten = cbToWrite;
     
    1013782     * The logic here must match what StreamPlay does.
    1014783     */
    1015     uint32_t cbWritable;
    1016 #ifndef RT_OS_L4
    1017     count_info CountInfo = {0,0,0};
    1018     if (pStreamOSS->Out.fMMIO)
    1019     {
    1020         /* Get current playback pointer. */
    1021         int rc2 = ioctl(pStreamOSS->hFile, SNDCTL_DSP_GETOPTR, &CountInfo);
    1022         AssertMsgReturn(rc2 >= 0, ("SNDCTL_DSP_GETOPTR failed: %s (%d)\n", strerror(errno), errno), 0);
    1023 
    1024         int cbData;
    1025         if (CountInfo.ptr >= pStreamOSS->old_optr)
    1026             cbData = CountInfo.ptr - pStreamOSS->old_optr;
    1027         else
    1028             cbData = pStreamOSS->cbBuf + CountInfo.ptr - pStreamOSS->old_optr;
    1029         Assert(cbData >= 0);
    1030         cbWritable = (unsigned)cbData;
    1031     }
    1032     else
     784    audio_buf_info abinfo = { 0, 0, 0, 0 };
     785    int rc2 = ioctl(pStreamOSS->hFile, SNDCTL_DSP_GETOSPACE, &abinfo);
     786    AssertMsgReturn(rc2 >= 0, ("SNDCTL_DSP_GETOSPACE failed: %s (%d)\n", strerror(errno), errno), 0);
     787
     788#if 0 /** @todo we could return abinfo.bytes here iff StreamPlay didn't use the fragmented approach */
     789    /** @todo r=bird: WTF do we make a fuss over abinfo.bytes for when we don't even use it?!? */
     790    AssertLogRelMsgReturn(abinfo.bytes >= 0, ("OSS: Warning: Invalid available size: %d\n", abinfo.bytes), VERR_INTERNAL_ERROR_3);
     791    if ((unsigned)abinfo.bytes > cbBuf)
     792    {
     793        LogRel2(("OSS: Warning: Too big output size (%d > %RU32), limiting to %RU32\n", abinfo.bytes, cbBuf, cbBuf));
     794        abinfo.bytes = cbBuf;
     795        /* Keep going. */
     796    }
    1033797#endif
    1034     {
    1035         audio_buf_info abinfo = { 0, 0, 0, 0 };
    1036         int rc2 = ioctl(pStreamOSS->hFile, SNDCTL_DSP_GETOSPACE, &abinfo);
    1037         AssertMsgReturn(rc2 >= 0, ("SNDCTL_DSP_GETOSPACE failed: %s (%d)\n", strerror(errno), errno), 0);
    1038 
    1039 #if 0 /** @todo we could return abinfo.bytes here iff StreamPlay didn't use the fragmented approach */
    1040         /** @todo r=bird: WTF do we make a fuss over abinfo.bytes for when we don't even use it?!? */
    1041         AssertLogRelMsgReturn(abinfo.bytes >= 0, ("OSS: Warning: Invalid available size: %d\n", abinfo.bytes), VERR_INTERNAL_ERROR_3);
    1042         if ((unsigned)abinfo.bytes > cbBuf)
    1043         {
    1044             LogRel2(("OSS: Warning: Too big output size (%d > %RU32), limiting to %RU32\n", abinfo.bytes, cbBuf, cbBuf));
    1045             abinfo.bytes = cbBuf;
    1046             /* Keep going. */
    1047         }
    1048 #endif
    1049 
    1050         cbWritable = (uint32_t)(abinfo.fragments * abinfo.fragsize);
    1051     }
    1052     cbWritable = RT_MIN(cbWritable, pStreamOSS->cbBuf);
    1053     return cbWritable;
     798
     799    return (uint32_t)(abinfo.fragments * abinfo.fragsize);
    1054800}
    1055801
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