in libftl/media.c [1409:1513]
OS_THREAD_ROUTINE ping_thread(void *data) {
ftl_stream_configuration_private_t *ftl = (ftl_stream_configuration_private_t *)data;
ftl_media_config_t *media = &ftl->media;
struct timeval lastSenderReportSendTime_tv;
senderReport_pkt_t *senderReport;
nack_slot_t senderReportSlot;
ping_pkt_t *ping;
nack_slot_t pingSlot;
ping = (ping_pkt_t*)pingSlot.packet;
senderReport = (senderReport_pkt_t*)senderReportSlot.packet;
pingSlot.len = sizeof(ping_pkt_t);
senderReportSlot.len = sizeof(senderReport_pkt_t);
// RTPC Header Format
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |V=2|P| FMT | PT | length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
uint8_t fmt = 1;
uint8_t ptype = PING_PTYPE;
ping->header = htonl((2 << 30) | (fmt << 24) | (ptype << 16) | sizeof(ping_pkt_t));
fmt = 0;
ptype = SENDER_REPORT_PTYPE;
senderReport->header = htonl((2 << 30) | (fmt << 24) | (ptype << 16) | ((sizeof(senderReport_pkt_t) / 4) - 1));
while (ftl_get_state(ftl, FTL_PING_THRD)) {
os_semaphore_pend(&ftl->media.ping_thread_shutdown, PING_TX_INTERVAL_MS);
// Get the current time in ntp
struct timeval currentTime;
gettimeofday(¤tTime, NULL);
// It's important that this is a disable check not an enable check
// because it is possible that this flag will be set before this thread spawns.
// In that case we don't want to overwrite the flag with the FTL_PING_THRD set above.
if (!ftl_get_state(ftl, FTL_DISABLE_TX_PING_PKTS))
{
ping->xmit_time.tv_sec = currentTime.tv_sec;
ping->xmit_time.tv_usec = currentTime.tv_usec;
_media_send_slot(ftl, &pingSlot);
}
if (!ftl_get_state(ftl, FTL_DISABLE_TX_SENDER_REPORT))
{
uint64_t timeSinceLastSRSendMs = timeval_subtract_to_ms(¤tTime, &lastSenderReportSendTime_tv);
if (timeSinceLastSRSendMs > SENDER_REPORT_TX_INTERVAL_MS)
{
lastSenderReportSendTime_tv = currentTime;
// For each media component...
ftl_media_component_common_t *media_comp[] = { &ftl->video.media_component, &ftl->audio.media_component };
ftl_media_component_common_t *comp;
int mediaCount = 0;
for (mediaCount = 0; mediaCount < sizeof(media_comp) / sizeof(media_comp[0]); mediaCount++) {
comp = media_comp[mediaCount];
// Ensure the stream has been started.
if (comp->base_dts_usec < 0)
{
continue;
}
// Set the ssrc and packet counts
senderReport->ssrc = htonl(comp->ssrc);
senderReport->senderOctetCount = htonl((uint32_t)comp->stats.payload_bytes_sent);
senderReport->senderPacketCount = htonl((uint32_t)comp->stats.packets_sent);
// Grab the last rtp timestamp. Since this is multi threaded we need it locally to ensure it doesn't change.
uint64_t timestamp = comp->timestamp;
uint64_t timestamp_dts_usec = comp->timestamp_dts_usec;
senderReport->rtpTimestamp = htonl((uint32_t)timestamp);
// For the NTP time, we will take the base ntp time for this stream and increment it by the amount of time
// that has passed from this rtp timestamp and the base timestamp. This way all of the values are derived from
// the timestamps we are passed from the client. The base time of the ntp clock doesn't really matter, it can't be
// trusted off this computer anyways due to clock sync. The ntp time is only use to relatively to compare SR reports.
uint64_t timeDiff_usec = timestamp_dts_usec - comp->base_dts_usec;
struct timeval srNtpTimestamp = media->sender_report_base_ntp;
timeval_add_us(&srNtpTimestamp, timeDiff_usec);
uint64_t ntpTimestamp = timeval_to_ntp(&srNtpTimestamp);
senderReport->ntpTimestampHigh = htonl(ntpTimestamp >> 32);
senderReport->ntpTimestampLow = htonl((uint32_t)(ntpTimestamp));
// Send the report
_media_send_slot(ftl, &senderReportSlot);
}
}
}
}
FTL_LOG(ftl, FTL_LOG_INFO, "Exited Ping Thread\n");
return 0;
}