VirtualBox

Changeset 86563 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Oct 14, 2020 8:17:11 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
140912
Message:

Audio/DrvAudio: Try harder re-initializing streams on host audio device changes. bugref:8658 (c11)

File:
1 edited

Legend:

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

    r86561 r86563  
    764764    PPDMAUDIOSTREAM pStream;
    765765    RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, Node)
     766    {
    766767        pStream->fStatus |= PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT;
     768        pStream->cTriesReInit   = 0;
     769        pStream->tsLastReInitNs = 0;
     770    }
    767771
    768772# ifdef VBOX_WITH_AUDIO_ENUM
     
    780784 * on the host side has changed.
    781785 *
     786 * Note: Does not touch the stream's status flags.
     787 *
    782788 * @returns IPRT status code.
    783789 * @param   pThis               Pointer to driver instance.
     
    794800     * Gather current stream status.
    795801     */
    796     bool fIsEnabled = RT_BOOL(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED); /* Stream is enabled? */
     802    const bool fIsEnabled = RT_BOOL(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED); /* Stream is enabled? */
    797803
    798804    /*
     
    869875
    870876    pStream->fStatus = PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED;
    871 
    872877#ifdef VBOX_WITH_STATISTICS
    873878    /*
     
    11111116 * Re-initializes the given stream if it is scheduled for this operation.
    11121117 *
    1113  * @returns VBox status code.
    11141118 * @param   pThis               Pointer to driver instance.
    11151119 * @param   pStream             Stream to check and maybe re-initialize.
    11161120 */
    1117 static int drvAudioStreamMaybeReInit(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
    1118 {
    1119     int rc = VINF_SUCCESS;
    1120 
     1121static void drvAudioStreamMaybeReInit(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
     1122{
    11211123    if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT)
    11221124    {
     1125        const unsigned cMaxTries = 3; /** @todo Make this configurable? */
     1126        const uint64_t tsNowNs   = RTTimeNanoTS();
     1127
     1128        /* Throttle re-initializing streams on failure. */
     1129        if (   pStream->cTriesReInit < cMaxTries
     1130            && tsNowNs - pStream->tsLastReInitNs >= RT_NS_1SEC * pStream->cTriesReInit) /** @todo Ditto. */
     1131        {
    11231132#ifdef VBOX_WITH_AUDIO_ENUM
    1124         if (pThis->fEnumerateDevices)
    1125         {
    1126             /* Re-enumerate all host devices. */
    1127             drvAudioDevicesEnumerateInternal(pThis, true /* fLog */, NULL /* pDevEnum */);
    1128 
    1129             pThis->fEnumerateDevices = false;
    1130         }
     1133            if (pThis->fEnumerateDevices)
     1134            {
     1135                /* Re-enumerate all host devices. */
     1136                drvAudioDevicesEnumerateInternal(pThis, true /* fLog */, NULL /* pDevEnum */);
     1137
     1138                pThis->fEnumerateDevices = false;
     1139            }
    11311140#endif /* VBOX_WITH_AUDIO_ENUM */
    11321141
    1133         /* Remove the pending re-init flag in any case, regardless whether the actual re-initialization succeeded
    1134          * or not. If it failed, the backend needs to notify us again to try again at some later point in time. */
    1135         pStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT;
    1136         rc = drvAudioStreamReInitInternal(pThis, pStream);
    1137     }
    1138 
    1139     return rc;
     1142            int rc = drvAudioStreamReInitInternal(pThis, pStream);
     1143            if (RT_FAILURE(rc))
     1144            {
     1145                pStream->cTriesReInit++;
     1146                pStream->tsLastReInitNs = tsNowNs;
     1147            }
     1148            else
     1149            {
     1150                /* Remove the pending re-init flag on success. */
     1151                pStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT;
     1152            }
     1153        }
     1154        else
     1155        {
     1156            /* Did we exceed our tries re-initializing the stream?
     1157             * Then this one is dead-in-the-water, so disable it for further use. */
     1158            if (pStream->cTriesReInit == cMaxTries)
     1159            {
     1160                LogRel(("Audio: Re-initializing stream '%s' exceeded maximum retries (%u), leaving as disabled\n",
     1161                        pStream->szName, cMaxTries));
     1162
     1163                /* Don't try to re-initialize anymore and mark as disabled. */
     1164                pStream->fStatus &= ~(PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT | PDMAUDIOSTREAMSTS_FLAGS_ENABLED);
     1165
     1166                /* Note: Further writes to this stream go to / will be read from the bit bucket (/dev/null) from now on. */
     1167            }
     1168        }
     1169
     1170#ifdef LOG_ENABLED
     1171        char *pszStreamSts = dbgAudioStreamStatusToStr(pStream->fStatus);
     1172        Log3Func(("[%s] fStatus=%s\n", pStream->szName, pszStreamSts));
     1173        RTStrFree(pszStreamSts);
     1174#endif /* LOG_ENABLED */
     1175
     1176    }
    11401177}
    11411178
     
    11601197
    11611198    /* Is the stream scheduled for re-initialization? Do so now. */
    1162     int rc = drvAudioStreamMaybeReInit(pThis, pStream);
    1163     if (RT_FAILURE(rc))
    1164         return rc;
     1199    drvAudioStreamMaybeReInit(pThis, pStream);
    11651200
    11661201#ifdef LOG_ENABLED
     
    11791214    /* Whether to try closing a pending to close stream. */
    11801215    bool fTryClosePending = false;
     1216
     1217    int rc;
    11811218
    11821219    do
     
    29042941
    29052942    /* Is the stream scheduled for re-initialization? Do so now. */
    2906     int rc = drvAudioStreamMaybeReInit(pThis, pStream);
    2907     if (RT_FAILURE(rc)) /** @todo r=aeichner What is the correct operation in the failure case? */
    2908         LogRel(("Audio: Reinitializing the stream in drvAudioStreamGetStatus() failed with %Rrc\n", rc));
     2943    drvAudioStreamMaybeReInit(pThis, pStream);
    29092944
    29102945    PDMAUDIOSTREAMSTS fStrmStatus = pStream->fStatus;
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