VirtualBox

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


Ignore:
Timestamp:
Jun 7, 2021 12:56:21 AM (4 years ago)
Author:
vboxsync
Message:

DrvHostAudioPulseAudio: Always register underflow/overflow callbacks for statistics and LogRel2. bugref:9890

File:
1 edited

Legend:

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

    r89532 r89534  
    162162    pa_usec_t               tsLastReadWrittenUs;
    163163#endif
    164 #ifdef DEBUG
    165164    /** Number of occurred audio data underflows. */
    166165    uint32_t                cUnderflows;
    167 #endif
    168166    /** Pulse sample format and attribute specification. */
    169167    pa_sample_spec          SampleSpec;
     
    214212    /** The name of the output device to use. Empty string for default. */
    215213    char                    szOutputDev[256];
     214
     215    /** Number of buffer underruns (for all streams). */
     216    STAMCOUNTER             StatUnderruns;
     217    /** Number of buffer overruns (for all streams). */
     218    STAMCOUNTER             StatOverruns;
    216219} DRVHSTAUDPA;
    217220
     
    800803}
    801804
     805
     806/**
     807 * Underflow notification.
     808 */
     809static void drvHstAudPaStreamUnderflowStatsCallback(pa_stream *pStream, void *pvContext)
     810{
     811    PDRVHSTAUDPASTREAM pStreamPA = (PDRVHSTAUDPASTREAM)pvContext;
     812    AssertPtrReturnVoid(pStreamPA);
     813    AssertPtrReturnVoid(pStreamPA->pDrv);
     814
     815    /* This may happen when draining/corking, so don't count those. */
     816    if (!pStreamPA->pDrainOp)
     817        STAM_REL_COUNTER_INC(&pStreamPA->pDrv->StatUnderruns);
     818
     819    pStreamPA->cUnderflows++;
     820
     821    LogRel2(("PulseAudio: Warning: Hit underflow #%RU32%s%s\n", pStreamPA->cUnderflows,
     822             pStreamPA->pDrainOp && pa_operation_get_state(pStreamPA->pDrainOp) == PA_OPERATION_RUNNING ? " (draining)" : "",
     823             pStreamPA->pCorkOp  && pa_operation_get_state(pStreamPA->pCorkOp)  == PA_OPERATION_RUNNING ? " (corking)" : "" ));
     824
     825    if (LogRelIs2Enabled() || LogIs2Enabled())
     826    {
     827        pa_usec_t cUsLatency = 0;
     828        int       fNegative  = 0;
     829        pa_stream_get_latency(pStream, &cUsLatency, &fNegative);
     830        LogRel2(("PulseAudio: Latency now is %'RU64 us\n", cUsLatency));
     831
     832# ifdef LOG_ENABLED
     833        if (LogIs2Enabled())
     834        {
     835            const pa_timing_info *pTInfo = pa_stream_get_timing_info(pStream);
     836            AssertReturnVoid(pTInfo);
     837            const pa_sample_spec *pSpec  = pa_stream_get_sample_spec(pStream);
     838            AssertReturnVoid(pSpec);
     839            Log2Func(("writepos=%'RU64 us, readpost=%'RU64 us, age=%'RU64 us, latency=%'RU64 us (%RU32Hz %RU8ch)\n",
     840                      pa_bytes_to_usec(pTInfo->write_index, pSpec), pa_bytes_to_usec(pTInfo->read_index, pSpec),
     841                      pa_rtclock_now() - pStreamPA->tsStartUs, cUsLatency, pSpec->rate, pSpec->channels));
     842        }
     843# endif
     844    }
     845}
     846
     847
     848/**
     849 * Overflow notification.
     850 */
     851static void drvHstAudPaStreamOverflowStatsCallback(pa_stream *pStream, void *pvContext)
     852{
     853    PDRVHSTAUDPASTREAM pStreamPA = (PDRVHSTAUDPASTREAM)pvContext;
     854    AssertPtrReturnVoid(pStreamPA);
     855    AssertPtrReturnVoid(pStreamPA->pDrv);
     856
     857    STAM_REL_COUNTER_INC(&pStreamPA->pDrv->StatOverruns);
     858    LogRel2(("PulseAudio: Warning: Hit overflow.\n"));
     859    RT_NOREF(pStream);
     860}
     861
     862
    802863#ifdef DEBUG
    803 
    804864/**
    805865 * Debug PA callback: Need data to output.
     
    813873    Log2Func(("Requesting %zu bytes; Latency: %'RU64 us (rcPa=%d n=%d)\n", cbLen, cUsLatency, rcPa, fNegative));
    814874}
    815 
    816 
    817 /**
    818  * Debug PA callback: Underflow.  This may happen when draining/corking.
    819  */
    820 static void drvHstAudPaStreamUnderflowDebugCallback(pa_stream *pStream, void *pvContext)
    821 {
    822     PDRVHSTAUDPASTREAM pStreamPA = (PDRVHSTAUDPASTREAM)pvContext;
    823     AssertPtrReturnVoid(pStreamPA);
    824 
    825     pStreamPA->cUnderflows++;
    826 
    827     LogRel2(("PulseAudio: Warning: Hit underflow #%RU32%s%s\n", pStreamPA->cUnderflows,
    828              pStreamPA->pDrainOp && pa_operation_get_state(pStreamPA->pDrainOp) == PA_OPERATION_RUNNING ? " (draining)" : "",
    829              pStreamPA->pCorkOp  && pa_operation_get_state(pStreamPA->pCorkOp)  == PA_OPERATION_RUNNING ? " (corking)" : "" ));
    830 
    831 # if 0 /* bird: It's certifiably insane to make buffer changes here and make DEBUG build behave differently from RELEASE builds. */
    832     if (   pStreamPA->cUnderflows >= 6                /** @todo Make this check configurable. */
    833         && pStreamPA->cUsLatency  < 2U*RT_US_1SEC)
    834     {
    835         pStreamPA->cUsLatency = pStreamPA->cUsLatency * 3 / 2;
    836         LogRel2(("PulseAudio: Increasing output latency to %'RU64 us\n", pStreamPA->cUsLatency));
    837 
    838         pStreamPA->BufAttr.maxlength = pa_usec_to_bytes(pStreamPA->cUsLatency, &pStreamPA->SampleSpec);
    839         pStreamPA->BufAttr.tlength   = pa_usec_to_bytes(pStreamPA->cUsLatency, &pStreamPA->SampleSpec);
    840         pa_operation *pOperation = pa_stream_set_buffer_attr(pStream, &pStreamPA->BufAttr, NULL, NULL);
    841         if (pOperation)
    842             pa_operation_unref(pOperation);
    843         else
    844             LogRel2(("pa_stream_set_buffer_attr failed!\n"));
    845 
    846         pStreamPA->cUnderflows = 0;
    847     }
    848 # endif
    849 
    850     pa_usec_t cUsLatency = 0;
    851     int       fNegative  = 0;
    852     pa_stream_get_latency(pStream, &cUsLatency, &fNegative);
    853     LogRel2(("PulseAudio: Latency now is %'RU64 us\n", cUsLatency));
    854 
    855 # ifdef LOG_ENABLED
    856     if (LogIs2Enabled())
    857     {
    858         const pa_timing_info *pTInfo = pa_stream_get_timing_info(pStream);
    859         AssertReturnVoid(pTInfo);
    860         const pa_sample_spec *pSpec  = pa_stream_get_sample_spec(pStream);
    861         AssertReturnVoid(pSpec);
    862         Log2Func(("writepos=%'RU64 us, readpost=%'RU64 us, age=%'RU64 us, latency=%'RU64 us (%RU32Hz %RU8ch)\n",
    863                   pa_bytes_to_usec(pTInfo->write_index, pSpec), pa_bytes_to_usec(pTInfo->read_index, pSpec),
    864                   pa_rtclock_now() - pStreamPA->tsStartUs, cUsLatency, pSpec->rate, pSpec->channels));
    865     }
    866 # endif
    867 }
    868 
    869 
    870 /**
    871  * Debug PA callback: Overflow.  This may happen when draining/corking.
    872  */
    873 static void drvHstAudPaStreamOverflowDebugCallback(pa_stream *pStream, void *pvContext)
    874 {
    875     RT_NOREF(pStream, pvContext);
    876     Log2Func(("Warning: Hit overflow\n"));
    877 }
    878 
    879875#endif /* DEBUG */
    880876
     
    10091005     * Set the state callback, and in debug builds a few more...
    10101006     */
     1007    pa_stream_set_state_callback(pStream, drvHstAudPaStreamStateChangedCallback, pThis);
     1008    pa_stream_set_underflow_callback(pStream, drvHstAudPaStreamUnderflowStatsCallback, pStreamPA);
     1009    pa_stream_set_overflow_callback(pStream, drvHstAudPaStreamOverflowStatsCallback, pStreamPA);
    10111010#ifdef DEBUG
    1012     pa_stream_set_write_callback(       pStream, drvHstAudPaStreamReqWriteDebugCallback,  pStreamPA);
    1013     pa_stream_set_underflow_callback(   pStream, drvHstAudPaStreamUnderflowDebugCallback, pStreamPA);
    1014     if (pCfgAcq->enmDir == PDMAUDIODIR_OUT)
    1015         pa_stream_set_overflow_callback(pStream, drvHstAudPaStreamOverflowDebugCallback,  pStreamPA);
     1011    pa_stream_set_write_callback(pStream, drvHstAudPaStreamReqWriteDebugCallback, pStreamPA);
    10161012#endif
    1017     pa_stream_set_state_callback(       pStream, drvHstAudPaStreamStateChangedCallback,   pThis);
    10181013
    10191014    /*
     
    23422337    RTSemEventDestroy(pThis->InitStateChgCtx.hEvtInit);
    23432338    pThis->InitStateChgCtx.hEvtInit = NIL_RTSEMEVENT;
     2339
     2340    /*
     2341     * Register statistics.
     2342     */
     2343    if (RT_SUCCESS(rc))
     2344    {
     2345        PDMDrvHlpSTAMRegister(pDrvIns, &pThis->StatOverruns, STAMTYPE_COUNTER, "Overruns", STAMUNIT_OCCURENCES,
     2346                              "Pulse-server side buffer overruns (all streams)");
     2347        PDMDrvHlpSTAMRegister(pDrvIns, &pThis->StatUnderruns, STAMTYPE_COUNTER, "Underruns", STAMUNIT_OCCURENCES,
     2348                              "Pulse-server side buffer underruns (all streams)");
     2349    }
    23442350
    23452351    return rc;
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