VirtualBox

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


Ignore:
Timestamp:
Mar 25, 2021 10:34:19 AM (4 years ago)
Author:
vboxsync
Message:

DrvHostAudioOss: Cleaned up StreamPlay and unbroke it. bugref:9890

File:
1 edited

Legend:

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

    r88269 r88287  
    1616 */
    1717
     18
     19/*********************************************************************************************************************************
     20*   Header Files                                                                                                                 *
     21*********************************************************************************************************************************/
    1822#include <errno.h>
    1923#include <fcntl.h>
     
    3741*   Defines                                                                                                                      *
    3842*********************************************************************************************************************************/
    39 
    4043#if ((SOUND_VERSION > 360) && (defined(OSS_SYSINFO)))
    4144/* OSS > 3.6 has a new syscall available for querying a bit more detailed information
     
    5255*   Structures                                                                                                                   *
    5356*********************************************************************************************************************************/
    54 
    5557/**
    5658 * OSS host audio driver instance data.
     
    210212static int ossStreamOpen(const char *pszDev, int fOpen, POSSAUDIOSTREAMCFG pOSSReq, POSSAUDIOSTREAMCFG pOSSAcq, int *phFile)
    211213{
    212     int rc = VERR_AUDIO_STREAM_COULD_NOT_CREATE;
     214    int rc = VINF_SUCCESS;
    213215
    214216    int fdFile = -1;
     
    230232
    231233            case 2:
    232                 /** @todo r=bird: You're ASSUMING stuff about pOSSReq->Props.fSwapEndian and
    233                  *        the host endian here. */
    234                 iFormat = pOSSReq->Props.fSigned ? AFMT_S16_LE : AFMT_U16_LE;
     234                if (PDMAudioPropsIsLittleEndian(&pOSSReq->Props))
     235                    iFormat = pOSSReq->Props.fSigned ? AFMT_S16_LE : AFMT_U16_LE;
     236                else
     237                    iFormat = pOSSReq->Props.fSigned ? AFMT_S16_BE : AFMT_U16_BE;
    235238                break;
    236239
     
    290293        if (ioctl(fdFile, fIn ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE, &abinfo))
    291294        {
    292             LogRel(("OSS: Failed to retrieve %s buffer length: %s (%d)\n", fIn ? "input" : "output", strerror(errno), errno));
     295            LogRel(("OSS: Failed to retrieve %c"
     296                    "s buffer length: %s (%d)\n", fIn ? "input" : "output", strerror(errno), errno));
    293297            break;
    294298        }
     
    508512    }
    509513    else
    510     {
    511 #endif
     514#endif
     515    {
    512516        if (pStreamOSS->pvBuf)
    513517        {
     
    519523
    520524        pStreamOSS->cbBuf = 0;
    521 #ifndef RT_OS_L4
    522     }
    523 #endif
     525    }
    524526
    525527    ossStreamClose(&pStreamOSS->hFile);
     
    688690        }
    689691
    690         if (RT_SUCCESS(rc))
     692        if (RT_SUCCESS(rc)) /** @todo r=bird: great code structure ... */
    691693        {
    692694            pStreamOSS->Out.fMMIO = false;
     
    778780 */
    779781static DECLCALLBACK(int) drvHostOssAudioHA_StreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
    780                                                       const void *pvBuf, uint32_t uBufSize, uint32_t *puWritten)
    781 {
     782                                                      const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
     783{
     784    POSSAUDIOSTREAM pStreamOSS = (POSSAUDIOSTREAM)pStream;
     785    AssertPtrReturn(pStreamOSS, VERR_INVALID_POINTER);
    782786    RT_NOREF(pInterface);
    783     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    784 
    785     POSSAUDIOSTREAM pStreamOSS = (POSSAUDIOSTREAM)pStream;
    786 
    787     int rc = VINF_SUCCESS;
    788     uint32_t cbWrittenTotal = 0;
    789 
     787
     788    /*
     789     * Figure out now much to write.
     790     */
     791    uint32_t cbToWrite;
    790792#ifndef RT_OS_L4
    791     count_info cntinfo;
    792 #endif
    793 
    794     do
    795     {
    796         uint32_t cbAvail = uBufSize;
    797         uint32_t cbToWrite;
     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
     810#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    }
     828    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);
     836
     837    /*
     838     * Write.
     839     */
     840    uint32_t cbChunk  = cbToWrite;
     841    uint32_t offChunk = 0;
     842    while (cbChunk > 0)
     843    {
     844        ssize_t cbWritten = write(pStreamOSS->hFile, &pbBuf[offChunk], RT_MIN(cbChunk, (unsigned)s_OSSConf.fragsize));
     845        if (cbWritten >= 0)
     846        {
     847            AssertLogRelMsg(!(cbWritten & pStreamOSS->uAlign),
     848                            ("OSS: Misaligned write (written %#zx, alignment %#x)\n", cbWritten, pStreamOSS->uAlign));
     849
     850            Assert((uint32_t)cbWritten <= cbChunk);
     851            offChunk += (uint32_t)cbWritten;
     852            cbChunk  -= (uint32_t)cbWritten;
     853        }
     854        else
     855        {
     856            LogRel(("OSS: Failed writing output data: %s (%d)\n", strerror(errno), errno));
     857            return RTErrConvertFromErrno(errno);
     858        }
     859    }
    798860
    799861#ifndef RT_OS_L4
    800         if (pStreamOSS->Out.fMMIO)
    801         {
    802             /* Get current playback pointer. */
    803             int rc2 = ioctl(pStreamOSS->hFile, SNDCTL_DSP_GETOPTR, &cntinfo);
    804             if (!rc2)
    805             {
    806                 LogRel(("OSS: Failed to retrieve current playback pointer: %s\n", strerror(errno)));
    807                 rc = RTErrConvertFromErrno(errno);
    808                 break;
    809             }
    810 
    811             /* Nothing to play? */
    812             if (cntinfo.ptr == pStreamOSS->old_optr)
    813                 break;
    814 
    815             int cbData;
    816             if (cntinfo.ptr > pStreamOSS->old_optr)
    817                 cbData = cntinfo.ptr - pStreamOSS->old_optr;
    818             else
    819                 cbData = uBufSize + cntinfo.ptr - pStreamOSS->old_optr;
    820             Assert(cbData >= 0);
    821 
    822             cbToWrite = RT_MIN((unsigned)cbData, cbAvail);
    823         }
    824         else
    825         {
    826 #endif
    827             audio_buf_info abinfo;
    828             int rc2 = ioctl(pStreamOSS->hFile, SNDCTL_DSP_GETOSPACE, &abinfo);
    829             if (rc2 < 0)
    830             {
    831                 LogRel(("OSS: Failed to retrieve current playback buffer: %s\n", strerror(errno)));
    832                 rc = RTErrConvertFromErrno(errno);
    833                 break;
    834             }
    835 
    836             if ((size_t)abinfo.bytes > uBufSize)
    837             {
    838                 LogRel2(("OSS: Warning: Too big output size (%d > %RU32), limiting to %RU32\n", abinfo.bytes, uBufSize, uBufSize));
    839                 abinfo.bytes = uBufSize;
    840                 /* Keep going. */
    841             }
    842 
    843             if (abinfo.bytes < 0)
    844             {
    845                 LogRel2(("OSS: Warning: Invalid available size (%d vs. %RU32)\n", abinfo.bytes, uBufSize));
    846                 rc = VERR_INVALID_PARAMETER;
    847                 break;
    848             }
    849 
    850             cbToWrite = RT_MIN(unsigned(abinfo.fragments * abinfo.fragsize), cbAvail);
    851 #ifndef RT_OS_L4
    852         }
    853 #endif
    854         cbToWrite = RT_MIN(cbToWrite, pStreamOSS->cbBuf);
    855 
    856         while (cbToWrite)
    857         {
    858             uint32_t cbWritten = cbToWrite;
    859 
    860             memcpy(pStreamOSS->pvBuf, pvBuf, cbWritten);
    861 
    862             uint32_t cbChunk    = cbWritten;
    863             uint32_t cbChunkOff = 0;
    864             while (cbChunk)
    865             {
    866                 ssize_t cbChunkWritten = write(pStreamOSS->hFile, (uint8_t *)pStreamOSS->pvBuf + cbChunkOff,
    867                                                RT_MIN(cbChunk, (unsigned)s_OSSConf.fragsize));
    868                 if (cbChunkWritten < 0)
    869                 {
    870                     LogRel(("OSS: Failed writing output data: %s\n", strerror(errno)));
    871                     rc = RTErrConvertFromErrno(errno);
    872                     break;
    873                 }
    874 
    875                 if (cbChunkWritten & pStreamOSS->uAlign)
    876                 {
    877                     LogRel(("OSS: Misaligned write (written %z, expected %RU32)\n", cbChunkWritten, cbChunk));
    878                     break;
    879                 }
    880 
    881                 cbChunkOff += (uint32_t)cbChunkWritten;
    882                 Assert(cbChunkOff <= cbWritten);
    883                 Assert(cbChunk    >= (uint32_t)cbChunkWritten);
    884                 cbChunk    -= (uint32_t)cbChunkWritten;
    885             }
    886 
    887             Assert(cbToWrite >= cbWritten);
    888             cbToWrite      -= cbWritten;
    889             cbWrittenTotal += cbWritten;
    890         }
    891 
    892 #ifndef RT_OS_L4
    893         /* Update read pointer. */
    894         if (pStreamOSS->Out.fMMIO)
    895             pStreamOSS->old_optr = cntinfo.ptr;
    896 #endif
    897 
    898     } while(0);
    899 
    900     if (RT_SUCCESS(rc))
    901     {
    902         if (puWritten)
    903             *puWritten = cbWrittenTotal;
    904     }
    905 
    906     return rc;
     862    /* Update read pointer. */
     863    if (pStreamOSS->Out.fMMIO)
     864        pStreamOSS->old_optr = CountInfo.ptr;
     865#endif
     866
     867    *pcbWritten = cbToWrite;
     868    return VINF_SUCCESS;
    907869}
    908870
     
    10421004static DECLCALLBACK(uint32_t) drvHostOssAudioHA_StreamGetWritable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
    10431005{
    1044     RT_NOREF(pInterface, pStream);
    1045     return UINT32_MAX;
     1006    POSSAUDIOSTREAM pStreamOSS = (POSSAUDIOSTREAM)pStream;
     1007    AssertPtr(pStreamOSS);
     1008    RT_NOREF(pInterface);
     1009
     1010    /*
     1011     * Note! This logic was found in StreamPlay and corrected a little.
     1012     *
     1013     * The logic here must match what StreamPlay does.
     1014     */
     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
     1033#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;
    10461054}
    10471055
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