Exemplo n.º 1
0
static int streamxmit_retransmitRtp(STREAM_RTP_DEST_T *pDest) {
  STREAMXMIT_PKT_HDR_T *pktHdr;
  unsigned int idxRd;
  unsigned int count = 0;
  int lastWasExpired = 0;
  int rc;
  int haveRequestedRetransmission = 0;
  const PKTQUEUE_PKT_T *pQPkt = NULL;
  STREAM_XMIT_QUEUE_T *pAsyncQ = &pDest->asyncQ;
  TIME_VAL tvNow;
  struct timeval tv;
  float kbps;
  char tmp[128];

  tvNow = timer_GetTime();
  TV_FROM_TIMEVAL(tv, tvNow);

  pthread_mutex_lock(&pAsyncQ->mtx);
  idxRd = pAsyncQ->pQ->idxRd;
  //LOG(X_DEBUG("NACK streamxmit_iterate ... idxRd:%d, idxWr:%d / %d"), pAsyncQ->pQ->idxRd, pAsyncQ->pQ->idxWr, pAsyncQ->pQ->cfg.maxPkts);
  while(count++ < pAsyncQ->pQ->cfg.maxPkts) {

    pQPkt = &pAsyncQ->pQ->pkts[idxRd];

    if(!(pQPkt->flags & PKTQUEUE_FLAG_HAVEPKTDATA)) {
      //LOG(X_DEBUG("NACK streamxmit_iterate break at qid[%d]"), idxRd);
      break;
    }
    //LOG(X_DEBUG("NACK streamxmit_iterate check qid[%d] seqno:%d, %lld ms ago"), idxRd, ((STREAMXMIT_PKT_HDR_T *) pQPkt->xtra.pQUserData)->seqNum, (tvNow - ((STREAMXMIT_PKT_HDR_T *) pQPkt->xtra.pQUserData)->tvxmit)/1000);

    lastWasExpired = 0;

    if(!(pktHdr = (STREAMXMIT_PKT_HDR_T *) pQPkt->xtra.pQUserData)) {

      pAsyncQ->pQ->idxRd = idxRd;
      fprintf(stderr, "streamxmit_itertate should never get here... idxRd:%d\n", idxRd);

    } else if(pktHdr->tvXmit + (pAsyncQ->nackHistoryMs * TIME_VAL_MS) < tvNow) {
      //
      // The queue slot RTP sequence number came before the NACK starting sequence number
      // so the current queue content is before the scope of the NACK
      //
      if(pktHdr->doRetransmit > 0) {
        pktHdr->doRetransmit = -1;

        if(pDest->pstreamStats) {
          stream_abr_notifyBitrate(pDest->pstreamStats, &pDest->streamStatsMtx, 
                                   STREAM_ABR_UPDATE_REASON_NACK_AGED, .5f);
        }

      }
      pAsyncQ->pQ->idxRd = idxRd;
      pAsyncQ->pQ->pkts[idxRd].flags = 0;
      lastWasExpired = 1;
      //LOG(X_DEBUG("NACK streamxmit_iterate old here marked to -1 ... idxRd:%d, seqNum:%d"), idxRd, pktHdr->seqNum);

    } else if(pktHdr->doRetransmit > 0 && !pktHdr->rtcp) {

      if(pktHdr->tvLastRetransmit == 0 || 
         pktHdr->tvLastRetransmit + (RTP_RETRANSMIT_INTERVAL_MS * TIME_VAL_MS) < tvNow) {

        //
        // Ensure that the retransmission will not exceed our retransmission bitrate limit
        //
        if(pAsyncQ->retransmissionKbpsMax > 0 &&
          burstmeter_updateCounters(&pAsyncQ->retransmissionMeter, &tv) == 0 &&
          (kbps = (burstmeter_getBitrateBps(&pAsyncQ->retransmissionMeter)/THROUGHPUT_BYTES_IN_KILO_F)) >= pAsyncQ->retransmissionKbpsMax) {

          LOG(X_WARNING("RTP NACK retransmission bitrate %.3f >= %.3f  throttled pt:%d sequence:%d to %s:%d, for original %d ms ago."), 
                     kbps, pAsyncQ->retransmissionKbpsMax, pDest->pRtpMulti->init.pt, pktHdr->seqNum, 
                     FORMAT_NETADDR(pDest->saDstsRtcp, tmp, sizeof(tmp)), ntohs(INET_PORT(pDest->saDstsRtcp)),
                     (tvNow - pktHdr->tvXmit) / TIME_VAL_MS);

          if(pDest->pstreamStats) {
            stream_abr_notifyBitrate(pDest->pstreamStats, &pDest->streamStatsMtx,
                                     STREAM_ABR_UPDATE_REASON_NACK_THROTTLED, .5f);
          }

          pktHdr->doRetransmit = 0;
          pktHdr->tvLastRetransmit = tvNow; 

        } else {

          burstmeter_AddSample(&pAsyncQ->retransmissionMeter, pQPkt->len, &tv);

          //LOG(X_DEBUG("RTP NACK Retransmission bitrate: %.3f %s (%.3f bps)"),  (float) pAsyncQ->retransmissionMeter.meter.rangeMs/1000, burstmeter_printThroughputStr(buf, sizeof(buf), &pAsyncQ->retransmissionMeter), (float) burstmeter_getBitrateBps(&pAsyncQ->retransmissionMeter));

          //
          // Retransmit the RTP packet
          //
          LOG(X_DEBUG("RTP NACK retransmitting pt:%d sequence:%d, len:%d to %s:%d, original sent %d ms ago.  "
                      "Rate: %.3f pkts/s, %.3f b/s"), 
                    pDest->pRtpMulti->init.pt, pktHdr->seqNum, pQPkt->len, 
                    FORMAT_NETADDR(pDest->saDstsRtcp, tmp, sizeof(tmp)), ntohs(INET_PORT(pDest->saDstsRtcp)), 
                    (tvNow - pktHdr->tvXmit) / TIME_VAL_MS,
                    (float) burstmeter_getPacketratePs(&pAsyncQ->retransmissionMeter),
                    (float) burstmeter_getBitrateBps(&pAsyncQ->retransmissionMeter));

          if((rc = srtp_sendto(STREAM_RTP_PNETIOSOCK(*pDest), (void *) pQPkt->pData, pQPkt->len, 0,
                              (const struct sockaddr *) &pDest->saDsts, NULL, SENDTO_PKT_TYPE_RTP, 1)) < 0) {
          
            pktHdr->doRetransmit = -1;
          } else {
            pktHdr->doRetransmit = 0;
          }

          pktHdr->tvLastRetransmit = tvNow; 
          if(pDest->pstreamStats) {
            stream_abr_notifyBitrate(pDest->pstreamStats, &pDest->streamStatsMtx,
                                     STREAM_ABR_UPDATE_REASON_NACK_RETRANSMITTED, .5f);
          }

        }

      } else {
        haveRequestedRetransmission = 1;
      }
   
    }

    if(++idxRd >= pAsyncQ->pQ->cfg.maxPkts) {
      idxRd = 0;
    }
    if(lastWasExpired) {
      pAsyncQ->pQ->idxRd = idxRd;
    } 

  } // end of while...

  pAsyncQ->haveRequestedRetransmission = haveRequestedRetransmission;

  pthread_mutex_unlock(&pAsyncQ->mtx);

  return haveRequestedRetransmission;
}
Exemplo n.º 2
0
static char *dump_throughput(char *buf, unsigned int szbuf, const char *prfx,
                             THROUGHPUT_STATS_T *pS, int urlidx) {
    int rc;
    unsigned int idx;
    unsigned int idxbuf = 0;
    char buftmp[256];

    if(szbuf > 0) {
        buf[0] = '\0';
    }

    if(!pS) {
        return buf;
    }

    if(pS->written.bytes > 0) {

        burstmeter_printBytes(buftmp, sizeof(buftmp), pS->written.bytes);

        if((urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, "&out%d=%s", urlidx, buftmp)) > 0) ||
                (!urlidx &&  (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, ", %swrote: %s", prfx, buftmp)) > 0)) {
            idxbuf += rc;
        }

        for(idx = 0; idx < sizeof(pS->bitratesWr) / sizeof(pS->bitratesWr[0]); idx++) {

            if(pS->bitratesWr[idx].meter.rangeMs > 0) {

                //
                // Roll up any real-time rate based counters
                //
                burstmeter_updateCounters(&pS->bitratesWr[idx], NULL);

                burstmeter_printThroughput(buftmp, sizeof(buftmp), &pS->bitratesWr[idx]);

                rc = snprintf(&buf[idxbuf], szbuf - idxbuf, ", %.1f pkts/s", burstmeter_getPacketratePs(&pS->bitratesWr[idx]));
                idxbuf += rc;

                if((urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, "&out%.0fs%d=%s",
                                             (float) pS->bitratesWr[idx].meter.rangeMs/1000.0f, urlidx, buftmp)) > 0) ||
                        (!urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, ", %.0fs: %s",
                                                   (float) pS->bitratesWr[idx].meter.rangeMs/1000.0f, buftmp)) > 0)) {
                    idxbuf += rc;
                }
            }

        }
    }

    if(pS->read.bytes > 0) {

        burstmeter_printBytes(buftmp, sizeof(buftmp), pS->read.bytes);

        if((urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, "&in%d=%s", urlidx, buftmp)) > 0) ||
                (!urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, ", read: %s", buftmp)) > 0)) {
            idxbuf += rc;
        }

        for(idx = 0; idx < sizeof(pS->bitratesRd) / sizeof(pS->bitratesRd[0]); idx++) {

            if(pS->bitratesRd[idx].meter.rangeMs > 0) {

                burstmeter_printThroughput(buftmp, sizeof(buftmp), &pS->bitratesRd[idx]);

                if((urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, "&in%.0fs%d=%s",
                                             (float) pS->bitratesRd[idx].meter.rangeMs/1000.0f, urlidx, buftmp)) > 0) ||
                        (!urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, ", %.0fs: %s",
                                                   (float) pS->bitratesRd[idx].meter.rangeMs/1000.0f, buftmp)) > 0)) {
                    idxbuf += rc;
                }

            }
        }
    }

    if(pS->skipped.bytes > 0) {
        burstmeter_printBytes(buftmp, sizeof(buftmp), pS->skipped.bytes);

        if((urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, "&skip%d=%s", urlidx, buftmp)) > 0) ||
                (!urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, ", skipped: %s", buftmp)) > 0)) {
            idxbuf += rc;
        }
    }

    if(pS->read.bytes > 0) {
        burstmeter_printBytes(buftmp, sizeof(buftmp), pS->written.bytes - pS->read.bytes - pS->skipped.bytes);

        if((urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, "&queue%d=%s", urlidx, buftmp)) > 0) ||
                (!urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, ", queued: %s", buftmp)) > 0)) {
            idxbuf += rc;
        }

        //fprintf(fp, " %s", printDuration(buftmp, sizeof(buftmp), PTSF_MS(pS->tmLastWr.tm - pS->tmLastRd.tm)));
    }



    /*
    fprintf(fp, "\nwritten:%lld,%lld, read:%lld,%lld, skipped:%lld,%lld { delta:%lld,%lld %.3fms, tmLastWr:%.3f, tmLastRd:%.3f\n", pS->written.bytes, pS->written.slots, pS->read.bytes, pS->read.slots, pS->skipped.bytes, pS->skipped.slots, (pS->written.bytes - pS->read.bytes - pS->skipped.bytes), (pS->written.slots - pS->read.slots - pS->skipped.slots),PTSF_MS(pS->tmLastWr.tm- pS->tmLastRd.tm), PTSF(pS->tmLastWr.tm), PTSF(pS->tmLastRd.tm));

      for(idx = 0; idx < sizeof(pS->bitratesWr) / sizeof(pS->bitratesWr[0]); idx++) {
        if(pS->bitratesWr[idx].meter.rangeMs > 0) {
          fprintf(fp, "writer - [%d] %dms cur: %.2fKb/s max: %.2fKb/s ", idx, pS->bitratesWr[idx].meter.rangeMs, pS->bitratesWr[idx].meter.cur.bytes * (1000.0f / pS->bitratesWr[idx].meter.rangeMs) / 125.0f, pS->bitratesWr[idx].meter.max.bytes * (1000.0f / pS->bitratesWr[idx].meter.rangeMs) / 125.0f);
        }
     }
     fprintf(fp, "\n");

     for(idx = 0; idx < sizeof(pS->bitratesWr) / sizeof(pS->bitratesWr[0]); idx++) {
       if(pS->bitratesRd[idx].meter.rangeMs > 0) {
          fprintf(fp, "reader - [%d] %dms cur: %.2fKb/s max: %.2fKb/s ", idx, pS->bitratesRd[idx].meter.rangeMs, pS->bitratesRd[idx].meter.cur.bytes * (1000.0f / pS->bitratesRd[idx].meter.rangeMs) / 125.0f, pS->bitratesRd[idx].meter.max.bytes * (1000.0f / pS->bitratesRd[idx].meter.rangeMs) / 125.0f);
        }
      }
      fprintf(fp, "\n");
    */

    return buf;
}