diff options
| author | Daniel Rugerio <[email protected]> | 2021-08-13 15:05:12 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-08-13 15:05:12 -0700 |
| commit | 7895dd22785ddba5e973662ed942be3b3452b89d (patch) | |
| tree | 5c4572d5bfd076d3776a88c5757e37f3ed50c0e7 /audio/tests/KSPosTst/pintest.cpp | |
| parent | df47b2d284558fa9aacd19257153037e4ebba60e (diff) | |
audio: Updates for Windows 10 22000 (#655)
* Updates for Windows 10 22000.
* Change how WIL is consumed.
Diffstat (limited to 'audio/tests/KSPosTst/pintest.cpp')
| -rw-r--r-- | audio/tests/KSPosTst/pintest.cpp | 112 |
1 files changed, 82 insertions, 30 deletions
diff --git a/audio/tests/KSPosTst/pintest.cpp b/audio/tests/KSPosTst/pintest.cpp index 57e35b07..be659896 100644 --- a/audio/tests/KSPosTst/pintest.cpp +++ b/audio/tests/KSPosTst/pintest.cpp @@ -49,10 +49,13 @@ HRESULT CollectSampleData UINT64 u64Position; UINT64 positionHNS; UINT64 u64Frequency; - double testStartHns; LARGE_INTEGER liNow; - LARGE_INTEGER liFrequency; - QueryPerformanceFrequency(&liFrequency); + PLONGLONG frequency = &g_pKsPosTst->m_qpcFrequency; + PLONGLONG pBaseHns = &g_pKsPosTst->m_testBaseHns; + CRtThreadRegistration* threadPriority = &g_pKsPosTst->m_threadPriority; + + // Register with MMCSS + threadPriority->RegisterWithMMCSS(); VERIFY_SUCCEEDED(pHalfApp->InitializeEndpoint()); VERIFY_SUCCEEDED(pHalfApp->CreateSineToneDataBuffer(pHalfApp->m_pCurrentFormat.get())); @@ -61,10 +64,6 @@ HRESULT CollectSampleData // run the adapter sink pin VERIFY_SUCCEEDED(pHalfApp->StartStream()); - // Get a HNS reference from the begining of the test so the HNS from system and driver times won't be so large - QueryPerformanceCounter(&liNow); - testStartHns = (double)liNow.QuadPart * HNSTIME_UNITS_PER_SECOND / (double)liFrequency.QuadPart; - tStart = xGetTime(); Sleep(DELAY_FOR_STABILIZE); // Get the stream frequency in order to determine the time offset @@ -85,10 +84,12 @@ HRESULT CollectSampleData // only count this result if the GetPosition and GetTime happened relatively atomically if ((tPost - tPre) < 1.) { - double testHNS = (double)liNow.QuadPart * HNSTIME_UNITS_PER_SECOND / (double)liFrequency.QuadPart; + // Convert QPC to microseconds and then HNS. This is to prevent overflows from converting directly to HNS. + UINT64 testHNS = liNow.QuadPart * MICROSECONDS_PER_SECOND / *frequency; + testHNS *= HNSTIME_UNITS_PER_MICROSECOND; // In both sampling rate and jitter calculation, the time used is in milliseconds, so we can convert it right here - pPosSet[i].testTime = HNSTIME_TO_MILLISECONDS_DOUBLE(testHNS - testStartHns); - pPosSet[i].positionTime = HNSTIME_TO_MILLISECONDS_DOUBLE(positionHNS - testStartHns); + pPosSet[i].testTime = HNSTIME_TO_MILLISECONDS_DOUBLE(testHNS - *pBaseHns); + pPosSet[i].positionTime = HNSTIME_TO_MILLISECONDS_DOUBLE(positionHNS - *pBaseHns); // We store the values as seconds because it is easier to convert to bytes per second, on sampling rate calculation, and milliseconds, on jitter calculation. pPosSet[i].position = (double)u64Position / (double)u64Frequency; @@ -117,6 +118,9 @@ HRESULT CollectSampleData VERIFY_SUCCEEDED(pHalfApp->StopStream()); + // Unregister with MMCSS + threadPriority->UnRegisterWithMMCSS(); + // Did we get enough data? VERIFY_IS_TRUE(pResults->cPosSets >= 30); @@ -310,7 +314,7 @@ void Test_DriftAndJitter_Main results.perfResults.argPosSets = pPositionSet.get(); // collect the data ~~~~~~~~~~~~~~~~~ - VERIFY_SUCCEEDED(CollectSampleData(pHalfApp, &results, requestedPeriodicity)); + IF_FAILED_JUMP(CollectSampleData(pHalfApp, &results, requestedPeriodicity), Log); // Stop and cleanup the host stream since we are done collecting samples if (isLoopbackPin) @@ -322,10 +326,31 @@ void Test_DriftAndJitter_Main } // calculate drift ~~~~~~~~~~~~~~~~~~ - VERIFY_SUCCEEDED(CalculateSampleRate(&results)); + IF_FAILED_JUMP(CalculateSampleRate(&results), Log); // calculate Jitter ~~~~~~~~~~~~~~~~~ VERIFY_SUCCEEDED(CalculateJitter(&results)); + + return; + +Log: + // If the drift test or the collection of samples fail, + // there will be no logging of data (from inside the jitter test). + // So, log whatever available values here. + if (g_pKsPosTst->m_fLogHistograms) + { + PERF_RESULTS* data = &results.perfResults; + LOG(g_pBasicLog, "Report Reported Position"); + LOG(g_pBasicLog, "time position timestamp"); + LOG(g_pBasicLog, "(ms) (s) (ms)"); + LOG(g_pBasicLog, "========== ========== =========="); + for (UINT i = 0; i < data->cPosSets; i++) + { + LOG(g_pBasicLog, "%10.2f, %10.2f, %10.2f", data->argPosSets[i].testTime, data->argPosSets[i].position, data->argPosSets[i].positionTime); + } + } + + ERR(g_pBasicLog, "Drift and jitter test failed"); } // ------------------------------------------------------------------------------ @@ -367,6 +392,8 @@ void Test_Latency_Main (HNSTIME requestedPeriodicity) CHalfApp* pHostHalfApp = g_pKsPosTst->m_pHostHalf; NTSTATUS lTimerResStatus; BOOL isLoopbackPin = pHalfApp->m_ConnectorType == eLoopbackConnector; + PLONGLONG qpcFrequency = &g_pKsPosTst->m_qpcFrequency; + CRtThreadRegistration* threadPriority = &g_pKsPosTst->m_threadPriority; // Test will ignore Bluetooth devices until proper thresholds are in place. if (pHalfApp->m_bIsBluetooth) @@ -383,6 +410,9 @@ void Test_Latency_Main (HNSTIME requestedPeriodicity) return; } + // Register with MMCSS + threadPriority->RegisterWithMMCSS(); + // If it is a loopback pin, get the host pin and start the stream if (isLoopbackPin) { @@ -414,9 +444,7 @@ void Test_Latency_Main (HNSTIME requestedPeriodicity) double tPosPre = 0.0; double tPosPost = 0.0; - LARGE_INTEGER liFrequency = { 0 }; LARGE_INTEGER timeStamp = { 0 }; - QueryPerformanceFrequency(&liFrequency); // mark the time double tRunPre = xGetTime(); @@ -439,17 +467,27 @@ void Test_Latency_Main (HNSTIME requestedPeriodicity) tPosPost = xGetTime(); if (g_pKsPosTst->m_fLogHistograms) { - LOG(g_pBasicLog, "Testing first non-zero position reported: %u samples, %u HNS at %.03f ms", u64Position, driverHns, tPosPost - tRunPre); + LOG(g_pBasicLog, "Testing first non-zero position reported: %llu samples, %llu HNS at %.03f ms", u64Position, driverHns, tPosPost - tRunPre); } - // Fail if the cursor does not move within 500 ms - VERIFY_IS_TRUE((tPosPost - tRunPost) < 500.0); + // Warn if the cursor does not move within 500 ms. Do not fail the test as this might be because the test overslept. + if ((tPosPost - tRunPost) >= 500.0) + { + WARN(g_pBasicLog, "Pin did not report a position in 500 ms"); + break; + } } // Before stopping, get the frequency of the stream UINT64 u64Frequency; VERIFY_SUCCEEDED(pHalfApp->m_pAudioClock->GetFrequency(&u64Frequency)); + // Stop the endpoint + VERIFY_SUCCEEDED(pHalfApp->StopStream()); + + // Unregister with MMCSS + threadPriority->UnRegisterWithMMCSS(); + // the uncertainty in time is the max possible value minus the min possible value divided by 2 (for +/- purposes) double tMax = tPosPost - tRunPre; double tMin = tPosPre - tRunPost; @@ -460,19 +498,28 @@ void Test_Latency_Main (HNSTIME requestedPeriodicity) double tOffset = MILLISECONDS_PER_SECOND * (double)u64Position / (double)u64Frequency; // Calculate the difference in time of the position time versus the test time - UINT64 testHns = 10000000 * timeStamp.QuadPart / liFrequency.QuadPart; - INT64 timeDiff = testHns - driverHns; + // Convert QPC to microseconds and then HNS. This is to prevent overflows from converting directly to HNS. + UINT64 testHns = MICROSECONDS_PER_SECOND * timeStamp.QuadPart / *qpcFrequency; + testHns *= HNSTIME_UNITS_PER_MICROSECOND; + + // Make the HNS times smaller to avoid overflows (or underflows) + PLONGLONG pBaseHns = &g_pKsPosTst->m_testBaseHns; + INT64 adjustedTestHns = (INT64)(testHns - *pBaseHns); + INT64 adjustedDriverHns = (INT64)(driverHns - *pBaseHns); + + INT64 timeDiff = adjustedTestHns - adjustedDriverHns; // Compensate the positon to take this difference into account tOffset += (double)timeDiff / HNSTIME_UNITS_PER_MILLISECOND; if (g_pKsPosTst->m_fLogHistograms) { - LOG(g_pBasicLog, "Times (HNS): %u, %u", testHns, driverHns); - LOG(g_pBasicLog, "Time difference: %d HNS (%f ms)", timeDiff, (double)timeDiff / HNSTIME_UNITS_PER_MILLISECOND); - LOG(g_pBasicLog, "First non-zero position = %u at %g ms", u64Position, tAve); + LOG(g_pBasicLog, "Base test time: %lld HNS", *pBaseHns); + LOG(g_pBasicLog, "Times (HNS): %llu, %llu", testHns, driverHns); + LOG(g_pBasicLog, "Time difference: %lld HNS (%f ms)", timeDiff, (double)timeDiff / HNSTIME_UNITS_PER_MILLISECOND); + LOG(g_pBasicLog, "First non-zero position = %llu at %g ms", u64Position, tAve); LOG(g_pBasicLog, "Time offset / max time: %f ms / %f ms", tOffset, tMax); - LOG(g_pBasicLog, "Frequency: %lu", u64Frequency); + LOG(g_pBasicLog, "Frequency: %llu", u64Frequency); } double tLatency; @@ -485,16 +532,21 @@ void Test_Latency_Main (HNSTIME requestedPeriodicity) } LOG(g_pBasicLog, "Adjusted latency = %.03f ms (+/- %.3f ms)", tLatency, tUncertainty); - // if the reported position is outside the max time for this call (see tUncertainty calculation above), then fail - // temp fix until we know how far can be the data in front of the - // real time because of buffering - VERIFY_IS_FALSE(tOffset > tMax); + // In case the position reported by the pin (tOffset) is ahead of the run time of the pin (tMax), + // assume that position might have jitter and apply the propper limits instead of failing the test. + if (tOffset > tMax + JITTER_STD_THRESHOLD) + { + WARN(g_pBasicLog, "Pin's time offset is greater than the time it has been in the RUN state. This will become an error in the future."); + return; + } // Verify that the latency is within the threshold - VERIFY_IS_TRUE(tLatency <= LATENCY_THRESHOLD); // ms + if (tLatency > LATENCY_THRESHOLD) + { + WARN(g_pBasicLog, "The latency exceeds the acceptable threshold. This will become an error in the future."); + return; + } - // Stop the endpoint - VERIFY_SUCCEEDED(pHalfApp->StopStream()); // If this was a loopback pin, stop the host stream also if (isLoopbackPin) { |
