OS_THREAD_ROUTINE ping_thread()

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(&currentTime, 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(&currentTime, &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;
}