static inline bool listenerDoStream(tl_state_t *pTLState) { AVB_TRACE_ENTRY(AVB_TRACE_TL); if (!pTLState) { AVB_LOG_ERROR("Invalid TLState"); AVB_TRACE_EXIT(AVB_TRACE_TL); return FALSE; } openavb_tl_cfg_t *pCfg = &pTLState->cfg; listener_data_t *pListenerData = pTLState->pPvtListenerData; bool bRet = FALSE; if (pTLState->bStreaming) { U64 nowNS; pListenerData->nReportCalls++; // Try to receive a frame if (IS_OPENAVB_SUCCESS(openavbAvtpRx(pListenerData->avtpHandle))) { pListenerData->nReportFrames++; } CLOCK_GETTIME64(OPENAVB_TIMER_CLOCK, &nowNS); if (pCfg->report_seconds > 0) { if (nowNS > pListenerData->nextReportNS) { listenerShowStats(pListenerData, pTLState); openavbListenerAddStat(pTLState, TL_STAT_RX_CALLS, pListenerData->nReportCalls); openavbListenerAddStat(pTLState, TL_STAT_RX_FRAMES, pListenerData->nReportFrames); pListenerData->nReportCalls = 0; pListenerData->nReportFrames = 0; pListenerData->nextReportNS += (pCfg->report_seconds * NANOSECONDS_PER_SECOND); } } else if (pCfg->report_frames > 0 && pListenerData->nReportFrames != pListenerData->lastReportFrames) { if (pListenerData->nReportFrames % pCfg->report_frames == 1) { listenerShowStats(pListenerData, pTLState); pListenerData->lastReportFrames = pListenerData->nReportFrames; } } if (nowNS > pListenerData->nextSecondNS) { pListenerData->nextSecondNS += NANOSECONDS_PER_SECOND; bRet = TRUE; } } else { SLEEP_MSEC(1); bRet = TRUE; } AVB_TRACE_EXIT(AVB_TRACE_TL); return bRet; }
bool listenerStartStream(tl_state_t *pTLState) { AVB_TRACE_ENTRY(AVB_TRACE_TL); if (!pTLState) { AVB_LOG_ERROR("Invalid TLState"); AVB_TRACE_EXIT(AVB_TRACE_TL); return FALSE; } assert(!pTLState->bStreaming); openavb_tl_cfg_t *pCfg = &pTLState->cfg; listener_data_t *pListenerData = pTLState->pPvtListenerData; openavbRC rc = openavbAvtpRxInit(pTLState->pMediaQ, &pCfg->map_cb, &pCfg->intf_cb, pListenerData->ifname, &pListenerData->streamID, pListenerData->destAddr, pCfg->raw_rx_buffers, pCfg->rx_signal_mode, &pListenerData->avtpHandle); if (IS_OPENAVB_FAILURE(rc)) { AVB_LOG_ERROR("Failed to create AVTP stream"); AVB_TRACE_EXIT(AVB_TRACE_TL); return FALSE; } // Setup timers U64 nowNS; CLOCK_GETTIME64(OPENAVB_TIMER_CLOCK, &nowNS); pListenerData->nextReportNS = nowNS + (pCfg->report_seconds * NANOSECONDS_PER_SECOND); pListenerData->lastReportFrames = 0; pListenerData->nextSecondNS = nowNS + NANOSECONDS_PER_SECOND; // Clear counters pListenerData->nReportCalls = 0; pListenerData->nReportFrames = 0; // Clear stats openavbListenerClearStats(pTLState); // we're good to go! pTLState->bStreaming = TRUE; AVB_TRACE_EXIT(AVB_TRACE_TL); return TRUE; }
bool talkerStartStream(tl_state_t *pTLState) { AVB_TRACE_ENTRY(AVB_TRACE_TL); if (!pTLState) { AVB_LOG_ERROR("Invalid TLState"); AVB_TRACE_EXIT(AVB_TRACE_TL); return FALSE; } openavb_tl_cfg_t *pCfg = &pTLState->cfg; talker_data_t *pTalkerData = pTLState->pPvtTalkerData; assert(!pTLState->bStreaming); pTalkerData->wakeFrames = pCfg->max_interval_frames * pCfg->batch_factor; // Set a max_transmit_deficit_usec default if (pCfg->max_transmit_deficit_usec == 0) pCfg->max_transmit_deficit_usec = 50000; openavbRC rc = openavbAvtpTxInit(pTLState->pMediaQ, &pCfg->map_cb, &pCfg->intf_cb, pTalkerData->ifname, &pTalkerData->streamID, pTalkerData->destAddr, pCfg->max_transit_usec, pTalkerData->fwmark, pTalkerData->vlanID, pTalkerData->vlanPCP, pTalkerData->wakeFrames * pCfg->raw_tx_buffers, &pTalkerData->avtpHandle); if (IS_OPENAVB_FAILURE(rc)) { AVB_LOG_ERROR("Failed to create AVTP stream"); AVB_TRACE_EXIT(AVB_TRACE_TL); return FALSE; } avtp_stream_t *pStream = (avtp_stream_t *)(pTalkerData->avtpHandle); if (!pStream->pMapCB->map_transmit_interval_cb(pTLState->pMediaQ)) { pTalkerData->wakeRate = pTalkerData->classRate / pCfg->batch_factor; } else { // Override the class observation interval with the one provided by the mapping module. pTalkerData->wakeRate = pStream->pMapCB->map_transmit_interval_cb(pTLState->pMediaQ) / pCfg->batch_factor; } pTalkerData->sleepUsec = MICROSECONDS_PER_SECOND / pTalkerData->wakeRate; pTalkerData->intervalNS = NANOSECONDS_PER_SECOND / pTalkerData->wakeRate; U32 SRKbps = ((unsigned long)pTalkerData->classRate * (unsigned long)pCfg->max_interval_frames * (unsigned long)pStream->frameLen * 8L) / 1000; U32 DataKbps = ((unsigned long)pTalkerData->wakeRate * (unsigned long)pCfg->max_interval_frames * (unsigned long)pStream->frameLen * 8L) / 1000; AVB_LOGF_INFO(STREAMID_FORMAT", sr-rate=%" PRIu32 ", data-rate=%lu, frames=%" PRIu16 ", size=%" PRIu16 ", batch=%" PRIu32 ", sleep=%" PRIu64 "us, sr-Kbps=%d, data-Kbps=%d", STREAMID_ARGS(&pTalkerData->streamID), pTalkerData->classRate, pTalkerData->wakeRate, pTalkerData->tSpec.maxIntervalFrames, pTalkerData->tSpec.maxFrameSize, pCfg->batch_factor, pTalkerData->intervalNS / 1000, SRKbps, DataKbps); // number of intervals per report pTalkerData->wakesPerReport = pCfg->report_seconds * NANOSECONDS_PER_SECOND / pTalkerData->intervalNS; // counts of intervals and frames between reports pTalkerData->cntFrames = 0; pTalkerData->cntWakes = 0; // setup the initial times U64 nowNS; CLOCK_GETTIME64(OPENAVB_TIMER_CLOCK, &nowNS); // Align clock : allows for some performance gain nowNS = ((nowNS + (pTalkerData->intervalNS)) / pTalkerData->intervalNS) * pTalkerData->intervalNS; pTalkerData->nextReportNS = nowNS + (pCfg->report_seconds * NANOSECONDS_PER_SECOND); pTalkerData->nextSecondNS = nowNS + NANOSECONDS_PER_SECOND; pTalkerData->nextCycleNS = nowNS + pTalkerData->intervalNS; // Clear stats openavbTalkerClearStats(pTLState); // we're good to go! pTLState->bStreaming = TRUE; AVB_TRACE_EXIT(AVB_TRACE_TL); return TRUE; }
static inline bool talkerDoStream(tl_state_t *pTLState) { AVB_TRACE_ENTRY(AVB_TRACE_TL); if (!pTLState) { AVB_LOG_ERROR("Invalid TLState"); AVB_TRACE_EXIT(AVB_TRACE_TL); return FALSE; } openavb_tl_cfg_t *pCfg = &pTLState->cfg; talker_data_t *pTalkerData = pTLState->pPvtTalkerData; bool bRet = FALSE; if (pTLState->bStreaming) { U64 nowNS; if (!pCfg->tx_blocking_in_intf) { // sleep until the next interval SLEEP_UNTIL_NSEC(pTalkerData->nextCycleNS); //AVB_DBG_INTERVAL(8000, TRUE); // send the frames for this interval int i; for (i = pTalkerData->wakeFrames; i > 0; i--) { if (IS_OPENAVB_SUCCESS(openavbAvtpTx(pTalkerData->avtpHandle, i == 1, pCfg->tx_blocking_in_intf))) pTalkerData->cntFrames++; else break; } } else { // Interface module block option if (IS_OPENAVB_SUCCESS(openavbAvtpTx(pTalkerData->avtpHandle, TRUE, pCfg->tx_blocking_in_intf))) pTalkerData->cntFrames++; } if (pTalkerData->cntWakes++ % pTalkerData->wakeRate == 0) { // time to service the endpoint IPC bRet = TRUE; } CLOCK_GETTIME64(OPENAVB_TIMER_CLOCK, &nowNS); if (pCfg->report_seconds > 0) { if (nowNS > pTalkerData->nextReportNS) { S32 late = pTalkerData->wakesPerReport - pTalkerData->cntWakes; U64 bytes = openavbAvtpBytes(pTalkerData->avtpHandle); if (late < 0) late = 0; U32 txbuf = openavbAvtpTxBufferLevel(pTalkerData->avtpHandle); U32 mqbuf = openavbMediaQCountItems(pTLState->pMediaQ, TRUE); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, FALSE, "TX UID:%d, ", LOG_RT_DATATYPE_U16, &pTalkerData->streamID.uniqueID); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "calls=%ld, ", LOG_RT_DATATYPE_U32, &pTalkerData->cntWakes); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "frames=%ld, ", LOG_RT_DATATYPE_U32, &pTalkerData->cntFrames); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "late=%d, ", LOG_RT_DATATYPE_U32, &late); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "bytes=%lld, ", LOG_RT_DATATYPE_U64, &bytes); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "txbuf=%d, ", LOG_RT_DATATYPE_U32, &txbuf); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, LOG_RT_END, "mqbuf=%d, ", LOG_RT_DATATYPE_U32, &mqbuf); openavbTalkerAddStat(pTLState, TL_STAT_TX_CALLS, pTalkerData->cntWakes); openavbTalkerAddStat(pTLState, TL_STAT_TX_FRAMES, pTalkerData->cntFrames); openavbTalkerAddStat(pTLState, TL_STAT_TX_LATE, late); openavbTalkerAddStat(pTLState, TL_STAT_TX_BYTES, bytes); pTalkerData->cntFrames = 0; pTalkerData->cntWakes = 0; pTalkerData->nextReportNS = nowNS + (pCfg->report_seconds * NANOSECONDS_PER_SECOND); } } if (nowNS > pTalkerData->nextSecondNS) { pTalkerData->nextSecondNS += NANOSECONDS_PER_SECOND; bRet = TRUE; } if (!pCfg->tx_blocking_in_intf) { pTalkerData->nextCycleNS += pTalkerData->intervalNS; if ((pTalkerData->nextCycleNS + (pCfg->max_transmit_deficit_usec * 1000)) < nowNS) { // Hit max deficit time. Something must be wrong. Reset the cycle timer. // Align clock : allows for some performance gain nowNS = ((nowNS + (pTalkerData->intervalNS)) / pTalkerData->intervalNS) * pTalkerData->intervalNS; pTalkerData->nextCycleNS = nowNS + pTalkerData->intervalNS; } } } else { SLEEP(1); // time to service the endpoint IPC bRet = TRUE; } AVB_TRACE_EXIT(AVB_TRACE_TL); return bRet; }
static inline bool listenerDoStream(tl_state_t *pTLState) { AVB_TRACE_ENTRY(AVB_TRACE_TL); if (!pTLState) { AVB_LOG_ERROR("Invalid TLState"); AVB_TRACE_EXIT(AVB_TRACE_TL); return FALSE; } openavb_tl_cfg_t *pCfg = &pTLState->cfg; listener_data_t *pListenerData = pTLState->pPvtListenerData; bool bRet = FALSE; if (pTLState->bStreaming) { U64 nowNS; pListenerData->nReportCalls++; // Try to receive a frame if (IS_OPENAVB_SUCCESS(openavbAvtpRx(pListenerData->avtpHandle))) { pListenerData->nReportFrames++; } CLOCK_GETTIME64(OPENAVB_TIMER_CLOCK, &nowNS); if (pCfg->report_seconds > 0) { if (nowNS > pListenerData->nextReportNS) { U64 lost = openavbAvtpLost(pListenerData->avtpHandle); U64 bytes = openavbAvtpBytes(pListenerData->avtpHandle); U32 rxbuf = openavbAvtpRxBufferLevel(pListenerData->avtpHandle); U32 mqbuf = openavbMediaQCountItems(pTLState->pMediaQ, TRUE); U32 mqrdy = openavbMediaQCountItems(pTLState->pMediaQ, FALSE); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, FALSE, "RX UID:%d, ", LOG_RT_DATATYPE_U16, &pListenerData->streamID.uniqueID); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "calls=%ld, ", LOG_RT_DATATYPE_U32, &pListenerData->nReportCalls); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "frames=%ld, ", LOG_RT_DATATYPE_U32, &pListenerData->nReportFrames); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "lost=%lld, ", LOG_RT_DATATYPE_U64, &lost); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "bytes=%lld, ", LOG_RT_DATATYPE_U64, &bytes); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "rxbuf=%d, ", LOG_RT_DATATYPE_U32, &rxbuf); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "mqbuf=%d, ", LOG_RT_DATATYPE_U32, &mqbuf); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, LOG_RT_END, "mqrdy=%d", LOG_RT_DATATYPE_U32, &mqrdy); openavbListenerAddStat(pTLState, TL_STAT_RX_CALLS, pListenerData->nReportCalls); openavbListenerAddStat(pTLState, TL_STAT_RX_FRAMES, pListenerData->nReportFrames); openavbListenerAddStat(pTLState, TL_STAT_RX_LOST, lost); openavbListenerAddStat(pTLState, TL_STAT_RX_BYTES, bytes); pListenerData->nReportCalls = 0; pListenerData->nReportFrames = 0; pListenerData->nextReportNS += (pCfg->report_seconds * NANOSECONDS_PER_SECOND); } } if (nowNS > pListenerData->nextSecondNS) { pListenerData->nextSecondNS += NANOSECONDS_PER_SECOND; bRet = TRUE; } } else { SLEEP(1); bRet = TRUE; } AVB_TRACE_EXIT(AVB_TRACE_TL); return bRet; }
// This callback is called when acting as a listener. bool openavbIntfViewerRxCB(media_q_t *pMediaQ) { AVB_TRACE_ENTRY(AVB_TRACE_INTF_DETAIL); if (pMediaQ) { pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; if (!pPvtData) { AVB_LOG_ERROR("Private interface module data not allocated."); return FALSE; } media_q_item_t *pMediaQItem = openavbMediaQTailLock(pMediaQ, pPvtData->ignoreTimestamp); if (pMediaQItem) { // The skip countdown allow the viewer modes to set a number of packets to ignore // after logging to reduce or eliminate the logging from affecting the stats. if (pPvtData->skipCountdown) pPvtData->skipCountdown--; if (pMediaQItem->dataLen && !pPvtData->skipCountdown) { pPvtData->servicedCount++; if (pPvtData->viewType == VIEWER_MODE_DETAIL) { U32 avtpTimestamp; U64 avtpTimestampTime; bool avtpTimestampValid; U32 nowTimestamp; U64 nowTimestampTime; bool nowTimestampValid; U64 nowTime; S32 lateNS = 0; U64 gapNS = 0; avtpTimestamp = openavbAvtpTimeGetAvtpTimestamp(pMediaQItem->pAvtpTime); avtpTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); avtpTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); nowTimestamp = openavbAvtpTimeGetAvtpTimestamp(pMediaQItem->pAvtpTime); nowTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); nowTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); CLOCK_GETTIME64(OPENAVB_CLOCK_REALTIME, &nowTime); if (avtpTimestampValid && nowTimestampValid) { lateNS = nowTimestampTime - avtpTimestampTime; if (lateNS > pPvtData->maxLateNS) { pPvtData->maxLateNS = lateNS; } pPvtData->accumLateNS += lateNS; if (pPvtData->servicedCount > 1) { gapNS = nowTime - pPvtData->prevNowTime; if (gapNS > pPvtData->maxGapNS) { pPvtData->maxGapNS = gapNS; } pPvtData->accumGapNS += gapNS; } pPvtData->prevNowTime = nowTime; if ((pPvtData->servicedCount % pPvtData->viewInterval) == 0) { S32 lateAvg = pPvtData->accumLateNS / pPvtData->servicedCount; S32 gapAvg = pPvtData->accumGapNS / (pPvtData->servicedCount - 1); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "****************************", LOG_RT_DATATYPE_CONST_STR, NULL); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Packets: %u", LOG_RT_DATATYPE_U32, &pPvtData->servicedCount); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "AVTP Timestamp: %u NS", LOG_RT_DATATYPE_U32, &avtpTimestamp); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Now Timestamp: %u NS", LOG_RT_DATATYPE_U32, &nowTimestamp); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Late: %d NS", LOG_RT_DATATYPE_S32, &lateNS); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Late Avg: %d NS", LOG_RT_DATATYPE_S32, &lateAvg); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Late Max: %d NS", LOG_RT_DATATYPE_S32, &pPvtData->maxLateNS); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Gap: %u NS", LOG_RT_DATATYPE_U32, &gapNS); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Gap Avg: %u NS", LOG_RT_DATATYPE_U32, &gapAvg); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Gap Max: %u NS", LOG_RT_DATATYPE_U32, &pPvtData->maxGapNS); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Data length: %u", LOG_RT_DATATYPE_U32, &pMediaQItem->dataLen); pPvtData->accumLateNS = 0; pPvtData->maxLateNS = 0; pPvtData->accumGapNS = 0; pPvtData->maxGapNS = 0; pPvtData->prevNowTime = 0; pPvtData->servicedCount = 0; pPvtData->skipCountdown = 10; } } } else if (pPvtData->viewType == VIEWER_MODE_MAPPING_AWARE) { } else if (pPvtData->viewType == VIEWER_MODE_AVTP_TIMESTAMP) { U64 avtpTimestampTime; bool avtpTimestampValid; S32 deltaNS = 0; avtpTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); avtpTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); if (avtpTimestampValid) { if (pPvtData->servicedCount > 1) { deltaNS = avtpTimestampTime - pPvtData->prevAvtpTimestampTime; if (deltaNS > pPvtData->maxAvtpDeltaNS) { pPvtData->maxAvtpDeltaNS = deltaNS; } pPvtData->accumAvtpDeltaNS += deltaNS; if (pPvtData->avgForJitter != 0) { S32 deltaJitter = pPvtData->avgForJitter - deltaNS; if (deltaJitter < 0) deltaJitter = -deltaJitter; pPvtData->jitter += (1.0/16.0) * ((float)deltaJitter - pPvtData->jitter); } } pPvtData->prevAvtpTimestampTime = avtpTimestampTime; if ((pPvtData->servicedCount % pPvtData->viewInterval) == 0) { S32 deltaAvg = pPvtData->accumAvtpDeltaNS / (pPvtData->servicedCount - 1); U32 jitter = (U32)(pPvtData->jitter); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, FALSE, "AVTP Timestamp Delta: %d NS ", LOG_RT_DATATYPE_S32, &deltaNS); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "AVTP Timestamp Delta Avg: %d NS ", LOG_RT_DATATYPE_S32, &deltaAvg); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "AVTP Timestamp Delta Max: %d NS ", LOG_RT_DATATYPE_S32, &pPvtData->maxAvtpDeltaNS); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, LOG_RT_END, "Jitter: %d", LOG_RT_DATATYPE_S32, &jitter); pPvtData->accumAvtpDeltaNS = 0; pPvtData->maxAvtpDeltaNS = 0; pPvtData->servicedCount = 0; pPvtData->prevAvtpTimestampTime = 0; pPvtData->skipCountdown = 10; pPvtData->jitter = 0.0; pPvtData->avgForJitter = deltaAvg; } } } else if (pPvtData->viewType == VIEWER_MODE_LATENCY) { U64 avtpTimestampTime; bool avtpTimestampValid; U64 nowTimestampTime; bool nowTimestampValid; S32 lateNS = 0; avtpTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); avtpTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); nowTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); nowTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); if (avtpTimestampValid && nowTimestampValid) { lateNS = nowTimestampTime - avtpTimestampTime; if (lateNS > pPvtData->maxLateNS) { pPvtData->maxLateNS = lateNS; } pPvtData->accumLateNS += lateNS; if (pPvtData->avgForJitter != 0) { S32 lateJitter = pPvtData->avgForJitter - lateNS; if (lateJitter < 0) lateJitter = -lateJitter; pPvtData->jitter += (1.0/16.0) * ((float)lateJitter - pPvtData->jitter); } if ((pPvtData->servicedCount % pPvtData->viewInterval) == 0) { S32 lateAvg = pPvtData->accumLateNS / pPvtData->servicedCount; U32 jitter = (U32)(pPvtData->jitter); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, FALSE, "Latency: %d NS ", LOG_RT_DATATYPE_S32, &lateNS); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "Latency Avg: %d NS ", LOG_RT_DATATYPE_S32, &lateAvg); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "Latency Max: %d NS ", LOG_RT_DATATYPE_S32, &pPvtData->maxLateNS); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, LOG_RT_END, "Jitter: %d", LOG_RT_DATATYPE_S32, &jitter); pPvtData->accumLateNS = 0; pPvtData->maxLateNS = 0; pPvtData->servicedCount = 0; pPvtData->skipCountdown = 10; pPvtData->jitter = 0.0; pPvtData->avgForJitter = lateAvg; } } } else if (pPvtData->viewType == VIEWER_MODE_SELECTIVE_TIMESTAMP) { } else if (pPvtData->viewType == VIEWER_MODE_LATE) { U64 avtpTimestampTime; bool avtpTimestampValid; U64 nowTimestampTime; bool nowTimestampValid; S32 lateNS = 0; avtpTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); avtpTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); nowTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); nowTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); if (avtpTimestampValid && nowTimestampValid) { lateNS = nowTimestampTime - avtpTimestampTime; if (lateNS > pPvtData->maxLateNS) { pPvtData->maxLateNS = lateNS; } pPvtData->accumLateNS += lateNS; if (pPvtData->avgForJitter != 0) { S32 lateJitter = pPvtData->avgForJitter - lateNS; if (lateJitter < 0) lateJitter = -lateJitter; pPvtData->jitter += (1.0/16.0) * ((float)lateJitter - pPvtData->jitter); } if ((pPvtData->servicedCount % pPvtData->viewInterval) == 0) { S32 lateAvg = pPvtData->accumLateNS / pPvtData->servicedCount; U32 jitter = (U32)(pPvtData->jitter); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, FALSE, "Late: %d NS ", LOG_RT_DATATYPE_S32, &lateNS); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "Late Avg: %d NS ", LOG_RT_DATATYPE_S32, &lateAvg); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "Late Max: %d NS ", LOG_RT_DATATYPE_S32, &pPvtData->maxLateNS); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, LOG_RT_END, "Jitter: %d", LOG_RT_DATATYPE_S32, &jitter); pPvtData->accumLateNS = 0; pPvtData->maxLateNS = 0; pPvtData->servicedCount = 0; pPvtData->skipCountdown = 10; pPvtData->jitter = 0.0; pPvtData->avgForJitter = lateAvg; } } } else if (pPvtData->viewType == VIEWER_MODE_GAP) { U64 nowTime; U64 gapNS = 0; CLOCK_GETTIME64(OPENAVB_CLOCK_REALTIME, &nowTime); if (pPvtData->servicedCount > 1) { gapNS = nowTime - pPvtData->prevNowTime; if (gapNS > pPvtData->maxGapNS) { pPvtData->maxGapNS = gapNS; } pPvtData->accumGapNS += gapNS; if (pPvtData->avgForJitter != 0) { S32 gapJitter = pPvtData->avgForJitter - gapNS; if (gapJitter < 0) gapJitter = -gapJitter; pPvtData->jitter += (1.0/16.0) * ((float)gapJitter - pPvtData->jitter); } } pPvtData->prevNowTime = nowTime; if ((pPvtData->servicedCount % pPvtData->viewInterval) == 0) { S32 gapAvg = pPvtData->accumGapNS / (pPvtData->servicedCount - 1); U32 jitter = (U32)(pPvtData->jitter); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, FALSE, "Gap: %d NS ", LOG_RT_DATATYPE_S32, &gapNS); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "Gap Avg: %d NS ", LOG_RT_DATATYPE_S32, &gapAvg); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "Gap Max: %d NS ", LOG_RT_DATATYPE_S32, &pPvtData->maxGapNS); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, LOG_RT_END, "Jitter: %d", LOG_RT_DATATYPE_S32, &jitter); pPvtData->accumGapNS = 0; pPvtData->maxGapNS = 0; pPvtData->prevNowTime = 0; pPvtData->servicedCount = 0; pPvtData->skipCountdown = 10; pPvtData->jitter = 0.0; pPvtData->avgForJitter = gapAvg; } } } openavbMediaQTailPull(pMediaQ); } } AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); return TRUE; }