// This callback will be called for each AVB transmit interval. Commonly this will be
// 4000 or 8000 times  per second.
bool openavbIntfLoggerTxCB(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 = openavbMediaQHeadLock(pMediaQ);
		if (pMediaQItem) {
		  	U32 dataLen = avbLogGetMsg(pMediaQItem->pPubData, pMediaQItem->itemSize);
			if (dataLen) {
				pMediaQItem->dataLen = dataLen;
				openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime);
				openavbMediaQHeadPush(pMediaQ);
				AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL);
				return TRUE;
			}
			else {
				openavbMediaQHeadUnlock(pMediaQ);
			}
		}
		else {
			AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL);
			return FALSE;	// Media queue full
		}
	}
	AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL);
	return FALSE;
}
Example #2
0
bool openavbIntfMpeg2tsGstTxCB(media_q_t *pMediaQ)
{
	AVB_TRACE_ENTRY(AVB_TRACE_INTF_DETAIL);

	if (!pMediaQ)
	{
		AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL);
		return FALSE;
	}

	pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo;
	if (!pPvtData)
	{
		AVB_LOG_ERROR("Private interface module data not allocated.");
		return FALSE;
	}

	if (!pPvtData->appsink)
	{
		AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL);
		return FALSE;
	}

	media_q_item_t *pMediaQItem;
	GstAlBuf *txBuf;

	while (g_atomic_int_get(&pPvtData->nWaiting) > 0)
	{

		// Get a mediaQItem to hold the buffered data
		pMediaQItem = openavbMediaQHeadLock(pMediaQ);
		if (!pMediaQItem)
		{
			IF_LOG_INTERVAL(1000) AVB_LOG_ERROR("Media queue full");
			break;
		}

		/* Retrieve the buffer
		 */
		txBuf = gst_al_pull_buffer(pPvtData->appsink);

		if (txBuf)
		{
			g_atomic_int_add(&pPvtData->nWaiting, -1);
			if ( GST_AL_BUF_SIZE(txBuf) > pMediaQItem->itemSize )
			{
				AVB_LOGF_ERROR("GStreamer buffer too large (size=%d) for mediaQ item (dataLen=%d)",
				               GST_AL_BUF_SIZE(txBuf), pMediaQItem->itemSize);
				pMediaQItem->dataLen = 0;
				openavbMediaQHeadUnlock(pMediaQ);
			}
			else
			{
				memcpy(pMediaQItem->pPubData, GST_AL_BUF_DATA(txBuf), GST_AL_BUF_SIZE(txBuf));
				pMediaQItem->dataLen = GST_AL_BUF_SIZE(txBuf);
				openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime);
				openavbMediaQHeadPush(pMediaQ);
			}
			gst_al_buffer_unref(txBuf);
		}
		else
		{
			AVB_LOG_ERROR("GStreamer buffer pull failed");
			// assume the pipeline is empty
			g_atomic_int_set(&pPvtData->nWaiting, 0);
			// abandon the mediaq item
			pMediaQItem->dataLen = 0;
			openavbMediaQHeadUnlock(pMediaQ);
			// and get out
			break;
		}
	}

	AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL);
	return TRUE;
}
// 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;
}