in source/src/AppCommon.c [306:399]
static STATUS getIceCandidatePairStatsCallback(UINT32 timerId, UINT64 currentTime, UINT64 userData)
{
UNUSED_PARAM(timerId);
UNUSED_PARAM(currentTime);
STATUS retStatus = STATUS_SUCCESS;
PAppConfiguration pAppConfiguration = (PAppConfiguration) userData;
UINT32 i;
UINT64 currentMeasureDuration = 0;
DOUBLE averagePacketsDiscardedOnSend = 0.0;
DOUBLE averageNumberOfPacketsSentPerSecond = 0.0;
DOUBLE averageNumberOfPacketsReceivedPerSecond = 0.0;
DOUBLE outgoingBitrate = 0.0;
DOUBLE incomingBitrate = 0.0;
RtcStats rtcIceCandidatePairMetrics;
BOOL locked = FALSE;
CHK_WARN(pAppConfiguration != NULL, STATUS_APP_COMMON_NULL_ARG, "getPeriodicStats(): Passed argument is NULL");
rtcIceCandidatePairMetrics.requestedTypeOfStats = RTC_STATS_TYPE_CANDIDATE_PAIR;
// We need to execute this under the object lock due to race conditions that it could pose
MUTEX_LOCK(pAppConfiguration->appConfigurationObjLock);
locked = TRUE;
for (i = 0; i < pAppConfiguration->streamingSessionCount; ++i) {
if (STATUS_SUCCEEDED(
rtcPeerConnectionGetMetrics(pAppConfiguration->streamingSessionList[i]->pPeerConnection, NULL, &rtcIceCandidatePairMetrics))) {
currentMeasureDuration = (rtcIceCandidatePairMetrics.timestamp - pAppConfiguration->streamingSessionList[i]->rtcMetricsHistory.prevTs) /
HUNDREDS_OF_NANOS_IN_A_SECOND;
DLOGD("Current duration: %" PRIu64 " seconds", currentMeasureDuration);
if (currentMeasureDuration > 0) {
DLOGD("Selected local candidate ID: %s", rtcIceCandidatePairMetrics.rtcStatsObject.iceCandidatePairStats.localCandidateId);
DLOGD("Selected remote candidate ID: %s", rtcIceCandidatePairMetrics.rtcStatsObject.iceCandidatePairStats.remoteCandidateId);
// TODO: Display state as a string for readability
DLOGD("Ice Candidate Pair state: %d", rtcIceCandidatePairMetrics.rtcStatsObject.iceCandidatePairStats.state);
DLOGD("Nomination state: %s",
rtcIceCandidatePairMetrics.rtcStatsObject.iceCandidatePairStats.nominated ? "nominated" : "not nominated");
averageNumberOfPacketsSentPerSecond =
(DOUBLE)(rtcIceCandidatePairMetrics.rtcStatsObject.iceCandidatePairStats.packetsSent -
pAppConfiguration->streamingSessionList[i]->rtcMetricsHistory.prevNumberOfPacketsSent) /
(DOUBLE) currentMeasureDuration;
DLOGD("Packet send rate: %lf pkts/sec", averageNumberOfPacketsSentPerSecond);
averageNumberOfPacketsReceivedPerSecond =
(DOUBLE)(rtcIceCandidatePairMetrics.rtcStatsObject.iceCandidatePairStats.packetsReceived -
pAppConfiguration->streamingSessionList[i]->rtcMetricsHistory.prevNumberOfPacketsReceived) /
(DOUBLE) currentMeasureDuration;
DLOGD("Packet receive rate: %lf pkts/sec", averageNumberOfPacketsReceivedPerSecond);
outgoingBitrate = (DOUBLE)((rtcIceCandidatePairMetrics.rtcStatsObject.iceCandidatePairStats.bytesSent -
pAppConfiguration->streamingSessionList[i]->rtcMetricsHistory.prevNumberOfBytesSent) *
8.0) /
currentMeasureDuration;
DLOGD("Outgoing bit rate: %lf bps", outgoingBitrate);
incomingBitrate = (DOUBLE)((rtcIceCandidatePairMetrics.rtcStatsObject.iceCandidatePairStats.bytesReceived -
pAppConfiguration->streamingSessionList[i]->rtcMetricsHistory.prevNumberOfBytesReceived) *
8.0) /
currentMeasureDuration;
DLOGD("Incoming bit rate: %lf bps", incomingBitrate);
averagePacketsDiscardedOnSend = (DOUBLE)(rtcIceCandidatePairMetrics.rtcStatsObject.iceCandidatePairStats.packetsDiscardedOnSend -
pAppConfiguration->streamingSessionList[i]->rtcMetricsHistory.prevPacketsDiscardedOnSend) /
(DOUBLE) currentMeasureDuration;
DLOGD("Packet discard rate: %lf pkts/sec", averagePacketsDiscardedOnSend);
DLOGD("Current STUN request round trip time: %lf sec",
rtcIceCandidatePairMetrics.rtcStatsObject.iceCandidatePairStats.currentRoundTripTime);
DLOGD("Number of STUN responses received: %llu", rtcIceCandidatePairMetrics.rtcStatsObject.iceCandidatePairStats.responsesReceived);
pAppConfiguration->streamingSessionList[i]->rtcMetricsHistory.prevTs = rtcIceCandidatePairMetrics.timestamp;
pAppConfiguration->streamingSessionList[i]->rtcMetricsHistory.prevNumberOfPacketsSent =
rtcIceCandidatePairMetrics.rtcStatsObject.iceCandidatePairStats.packetsSent;
pAppConfiguration->streamingSessionList[i]->rtcMetricsHistory.prevNumberOfPacketsReceived =
rtcIceCandidatePairMetrics.rtcStatsObject.iceCandidatePairStats.packetsReceived;
pAppConfiguration->streamingSessionList[i]->rtcMetricsHistory.prevNumberOfBytesSent =
rtcIceCandidatePairMetrics.rtcStatsObject.iceCandidatePairStats.bytesSent;
pAppConfiguration->streamingSessionList[i]->rtcMetricsHistory.prevNumberOfBytesReceived =
rtcIceCandidatePairMetrics.rtcStatsObject.iceCandidatePairStats.bytesReceived;
pAppConfiguration->streamingSessionList[i]->rtcMetricsHistory.prevPacketsDiscardedOnSend =
rtcIceCandidatePairMetrics.rtcStatsObject.iceCandidatePairStats.packetsDiscardedOnSend;
}
}
}
CleanUp:
if (locked) {
MUTEX_UNLOCK(pAppConfiguration->appConfigurationObjLock);
}
return retStatus;
}