VirtualBox

Changeset 70594 in vbox


Ignore:
Timestamp:
Jan 15, 2018 4:35:07 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
120302
Message:

Audio/HDA: Fixes for Windows guest surround setups.

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

Legend:

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

    r70540 r70594  
    217217    }
    218218
     219    if (   !pStream->u32CBL
     220        || !pStream->u16LVI
     221        || !pStream->u64BDLBase
     222        || !pStream->u16FIFOS)
     223    {
     224        return VINF_SUCCESS;
     225    }
     226
    219227    /* Set the stream's frame size. */
    220228    pStream->State.cbFrameSize = pCfg->Props.cChannels * (pCfg->Props.cBits / 8 /* To bytes */);
     229    LogFunc(("[SD%RU8] cChannels=%RU8, cBits=%RU8 -> cbFrameSize=%RU32\n",
     230             pStream->u8SD, pCfg->Props.cChannels, pCfg->Props.cBits, pStream->State.cbFrameSize));
     231    Assert(pStream->State.cbFrameSize); /* Frame size must not be 0. */
    221232
    222233    /*
     
    235246             pStream->State.Cfg.Props.uHz, rc));
    236247
    237     if (   pStream->u32CBL
    238         && pStream->u16LVI)
     248    /* Make sure that mandatory parameters are set up correctly. */
     249    AssertStmt(pStream->u32CBL %  pStream->State.cbFrameSize == 0, rc = VERR_INVALID_PARAMETER);
     250    AssertStmt(pStream->u16LVI >= 1,                               rc = VERR_INVALID_PARAMETER);
     251
     252    if (RT_SUCCESS(rc))
    239253    {
    240254        /* Make sure that the chosen Hz rate dividable by the stream's rate. */
     
    263277            RT_ZERO(BDLE);
    264278
    265             Assert(pStream->u64BDLBase);
    266 
    267279            int rc2 = hdaBDLEFetch(pThis, &BDLE, pStream->u64BDLBase, 0 /* Entry */);
    268280            AssertRC(rc2);
    269281
    270             Assert(BDLE.Desc.u32BufSize % pStream->State.cbFrameSize == 0);
     282            /* Note: Do *not* check if this BDLE aligns to the stream's frame size.
     283             *       It can happen that this isn't the case on some guests, e.g.
     284             *       on Windows with a 5.1 speaker setup.
     285             *
     286             *       The only thing which counts is that the stream's CBL value
     287             *       properly aligns to the stream's frame size.
     288             */
    271289
    272290            /* If no custom set position adjustment is set, apply some
     
    340358        pStream->State.cbTransferProcessed        = 0;
    341359        pStream->State.cTransferPendingInterrupts = 0;
     360        pStream->State.cbDMALeft                  = 0;
    342361
    343362        const uint64_t cTicksPerHz = TMTimerGetFreq(pThis->pTimer) / pThis->u16TimerHz;
     
    366385#endif
    367386    }
     387
     388    if (RT_FAILURE(rc))
     389        LogRel(("HDA: Initializing stream #%RU8 failed with %Rrc\n", rc));
    368390
    369391    return rc;
     
    537559    AssertPtrReturnVoid(pStream);
    538560
    539     Assert(u32LPIB % pStream->State.cbFrameSize == 0);
    540 
    541561    Log3Func(("[SD%RU8] LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n",
    542562              pStream->u8SD, u32LPIB, pStream->pHDAState->fDMAPosition));
     
    937957            if (RT_SUCCESS(rc))
    938958            {
    939                 uint32_t cbDMAWritten = 0;
    940                 uint32_t cbDMALeft    = cbDMA;
    941 
    942                 if (cbDMALeft > RTCircBufFree(pCircBuf))
    943                 {
    944                     LogRel2(("HDA: FIFO overflow for stream #%RU8 (%RU32 bytes outstanding)\n",
    945                              pStream->u8SD, cbDMALeft - RTCircBufFree(pCircBuf)));
    946 
    947                     /* Try to read as much as possible. */
    948                     cbDMALeft = (uint32_t)RTCircBufFree(pCircBuf);
    949 
    950                     rc = VERR_BUFFER_OVERFLOW;
    951                 }
     959                uint32_t cbDMARead = pStream->State.cbDMALeft ? pStream->State.cbFrameSize - pStream->State.cbDMALeft : 0;
     960                uint32_t cbDMALeft = RT_MIN(cbDMA, RTCircBufFree(pCircBuf));
    952961
    953962#ifndef VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT
    954963                /**
    955964                 * The following code extracts the required audio stream (channel) data
    956                  * of non-interleaved  *and* interleaved audio streams.
     965                 * of non-interleaved *and* interleaved audio streams.
    957966                 *
    958967                 * We by default only support 2 channels with 16-bit samples (HDA_FRAME_SIZE),
     
    962971                 * So take this into account by just handling the first channel in such a stream ("A")
    963972                 * and just discard the other channel's data.
     973                 *
     974                 * @todo Optimize this stuff -- copying only one frame a time is expensive.
    964975                 */
    965                 while (cbDMALeft)
     976                while (cbDMALeft >= pStream->State.cbFrameSize)
    966977                {
    967978                    void *pvBuf; size_t cbBuf;
    968979                    RTCircBufAcquireWriteBlock(pCircBuf, HDA_FRAME_SIZE, &pvBuf, &cbBuf);
    969980
     981                    AssertBreak(cbDMARead <= sizeof(abChunk));
     982
    970983                    if (cbBuf)
    971                         memcpy(pvBuf, abChunk + cbDMAWritten, cbBuf);
     984                        memcpy(pvBuf, abChunk + cbDMARead, cbBuf);
    972985
    973986                    RTCircBufReleaseWriteBlock(pCircBuf, cbBuf);
    974987
    975                     cbDMALeft    -= (uint32_t)pStream->State.cbFrameSize;
    976                     cbDMAWritten += (uint32_t)pStream->State.cbFrameSize;
     988                    Assert(cbDMALeft >= pStream->State.cbFrameSize);
     989                    cbDMALeft -= pStream->State.cbFrameSize;
     990                    cbDMARead += pStream->State.cbFrameSize;
    977991                }
     992
     993                pStream->State.cbDMALeft = cbDMALeft;
     994                Assert(pStream->State.cbDMALeft < pStream->State.cbFrameSize);
     995
     996                const size_t cbFree = RTCircBufFree(pCircBuf);
     997                if (!cbFree)
     998                    LogRel2(("HDA: FIFO of stream #%RU8 full, discarding audio data\n", pStream->u8SD));
    978999#else
    9791000                /** @todo This needs making use of HDAStreamMap + HDAStreamChannel. */
     
    9921013        if (cbDMA)
    9931014        {
    994             Assert(cbDMA % pStream->State.cbFrameSize == 0);
    995 
    9961015            /* We always increment the position of DMA buffer counter because we're always reading
    9971016             * into an intermediate buffer. */
     
    10691088
    10701089    /* Sanity. */
    1071     Assert(cbProcessed % pStream->State.cbFrameSize == 0);
    10721090    Assert(cbProcessed == cbToProcess);
    10731091    Assert(cbLeft      == 0);
  • trunk/src/VBox/Devices/Audio/HDAStream.h

    r70248 r70594  
    171171    RTLISTANCHORR3          lstDMAHandlers;
    172172#endif
     173    /** How much DMA data from a previous transfer is left to be processed (in bytes).
     174     *  This can happen if the stream's frame size is bigger (e.g. 16 bytes) than
     175     *  the current DMA FIFO can hold (e.g. 10 bytes). Mostly needed for more complex
     176     *  stuff like interleaved surround streams. */
     177    uint16_t                cbDMALeft;
    173178    /** Unused, padding. */
    174     uint8_t                 Padding3[3];
     179    uint8_t                 Padding3;
    175180} HDASTREAMSTATE, *PHDASTREAMSTATE;
    176181
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