Exemplo n.º 1
0
void pool_close(POOL_T *pPool, int wait_for_ret) {

  TIME_VAL tv0 = timer_GetTime();

  if(!pPool) {
    return;
  }

  if(pPool->pInUse) {
    pPool->destroy_onempty = 1;

    if(wait_for_ret) {
      LOG(X_DEBUG("pool_close %s waiting for resources to be returned"), (pPool->descr ? pPool->descr : ""));
      while(pPool->pInUse) {
        if(wait_for_ret > 0 && (timer_GetTime() - tv0) / TIME_VAL_MS > wait_for_ret) {
          LOG(X_WARNING("pool_close %s aborting wait for resources to be returned"), (pPool->descr ? pPool->descr : ""));
          break;
        }
        usleep(50000);
      }
      LOG(X_DEBUG("pool_close %s done waiting for resources to be returned"), (pPool->descr ? pPool->descr : ""));
    } else {
      LOG(X_DEBUG("pool_close %s delaying deallocation until resources returned"), 
        (pPool->descr ? pPool->descr : ""));
      return;
    }

  }

  pool_free(pPool);

}
Exemplo n.º 2
0
int sys_mem_usage(SYS_USAGE_CTXT_T *pCtxt) {
  int rc = 0;
  TIME_VAL tmnow;

  if(!pCtxt || !pCtxt->pcurM) {
    return -1;
  }

  tmnow = timer_GetTime();

  //
  // Return if it has not yet been SYS_MEM_MIN_INTERVAL_MS since the last snapshot
  //
  if(pCtxt->memsnapshot.tvsnapshot != 0 && 
     ((tmnow - pCtxt->memsnapshot.tvsnapshot) / TIME_VAL_MS) < SYS_MEM_MIN_INTERVAL_MS) {
    LOG(X_DEBUGV("Memory snapshot not ready"));
    return 0;
  }
 
  //
  // Take a running snapshot of the cpu counters
  //
  if((rc = mem_snapshot(&pCtxt->memsnapshot, tmnow)) < 0)  {
    return rc;
  }

  memcpy(pCtxt->pcurM, &pCtxt->memsnapshot, sizeof(MEM_SNAPSHOT_T));

  return 1;
}
Exemplo n.º 3
0
enum STREAM_NET_ADVFR_RC stream_net_check_time(TIME_VAL *ptvStart, uint64_t *pframeId, unsigned int clockHz, 
                                               unsigned int frameDeltaHz, uint64_t *pPtsOut, int64_t *pPtsOffset) {
  TIME_VAL tvNow = timer_GetTime();
  double tvElapsed, tvEquiv;
  uint64_t us;

  if(*pframeId == 0) {
    *ptvStart = tvNow;
  } else if((tvElapsed = (double)(tvElapsed = (tvNow - *ptvStart))/1000) <
            (tvEquiv = (double)1000 * *pframeId * frameDeltaHz / clockHz)) {

    us = (tvEquiv - tvElapsed) * 1000;
    //fprintf(stderr, "streamnet_check_time notavail elapsed:%lldms, frameId:%lld, equiv of %.3f ms (%.3f, %.3f %llu us) %d/%dHz\n", (tvNow - *ptvStart)/1000,  *pframeId, (double)1000 * *pframeId / clockHz, tvElapsed, tvEquiv, us, clockHz, frameDeltaHz);

    if(us > 2000) {
      usleep(MIN(5000, us - 2000));
    }

    return STREAM_NET_ADVFR_RC_NOTAVAIL;
  }


  if(pPtsOut) {
    *pPtsOut = (uint64_t) 90000.0f * ((double) *pframeId * frameDeltaHz / clockHz);
    if(pPtsOffset) {
      if(*pPtsOffset < 0 && -1 * *pPtsOffset > *pPtsOut) {
        *pPtsOut = 0;
      } else {
        (*pPtsOut) += *pPtsOffset;
      }
    }
    //fprintf(stderr, "stream_net_check_time PTS:%.3f, frameId:%llu, clockHz:%uHz, deltaHz:%dHz, elapsed:%lldms, equiv of %.3fms %d/%dHz\n", PTSF(*pPtsOut), *pframeId, clockHz, frameDeltaHz, (tvNow - *ptvStart)/1000, (double) tvEquiv, clockHz, frameDeltaHz);
  }

  (*pframeId)++;

  return STREAM_NET_ADVFR_RC_OK;
}
Exemplo n.º 4
0
int srvlisten_loop(SRV_LISTENER_CFG_T *pListenCfg, void *thread_func) {

  int salen;
  THREAD_FUNC_WRAPPER_ARG_T wrapArg;
  CLIENT_CONN_T *pConn;
  SOCKET_DESCR_T sdclient;
  int rc = -1;
  const char *s;
  //pthread_cond_t cond;
  pthread_mutex_t mtx;
  TIME_VAL tv0, tv1;
  char tmp[128];

#if defined(__APPLE__) 
  int sockopt = 0;
#endif // __APPLE__

  if(!pListenCfg || !pListenCfg->pnetsockSrv || !pListenCfg->pConnPool || !thread_func || 
     pListenCfg->pConnPool->numElements <= 0) {
    return -1;
  }

  //memset(&saSrv, 0, sizeof(saSrv));
  memset(&sdclient.netsocket, 0, sizeof(sdclient.netsocket));
  //salen = sizeof(saSrv);

  //if(getsockname(pListenCfg->pnetsockSrv->sock, (struct sockaddr *) &saSrv,  (socklen_t *) &salen) != 0) {
  //  LOG(X_ERROR("getsockopt failed on server socket"));
  //}

  pthread_mutex_init(&mtx, NULL);
  //pthread_cond_init(&cond, NULL);

  while(!g_proc_exit) {

    salen = sizeof(sdclient.sa);
    if((NETIOSOCK_FD(sdclient.netsocket) = 
                 accept(PNETIOSOCK_FD(pListenCfg->pnetsockSrv), (struct sockaddr *) &sdclient.sa, 
                                      (socklen_t *) &salen)) == INVALID_SOCKET) {
      if(!g_proc_exit) {
        LOG(X_ERROR("%saccept failed on %s:%d"), 
             ((pListenCfg->pnetsockSrv->flags & NETIO_FLAG_SSL_TLS) ? "SSL " : ""),
                 //inet_ntoa(saSrv.sin_addr), ntohs(saSrv.sin_port));
                 FORMAT_NETADDR(pListenCfg->sa, tmp, sizeof(tmp)), ntohs(INET_PORT(pListenCfg->sa)));
      }
      break;
    }

    if(g_proc_exit) {
      break;
    }

    sdclient.netsocket.flags = pListenCfg->pnetsockSrv->flags;

    //
    // Find an available client thread to process the client request
    //
    if((pConn = (CLIENT_CONN_T *) pool_get(pListenCfg->pConnPool)) == NULL) {
      LOG(X_WARNING("No available connection for %s:%d (max:%d) on port %d"), 
           FORMAT_NETADDR(sdclient.sa, tmp, sizeof(tmp)), ntohs(INET_PORT(sdclient.sa)), 
           pListenCfg->pConnPool->numElements, ntohs(INET_PORT(pListenCfg->sa)));

      netio_closesocket(&sdclient.netsocket);
      continue;
    }

#if defined(__APPLE__) 
    sockopt = 1;
    if(setsockopt(NETIOSOCK_FD(sdclient.netsocket), SOL_SOCKET, SO_NOSIGPIPE,
                 (char*) &sockopt, sizeof(sockopt)) != 0) {
      LOG(X_ERROR("Failed to set SO_NOSIGPIPE"));
    }
#endif // __APPLE__

    //pConn->psrvsaListen = &saSrv;
    //memcpy(&pConn->srvsaListen, &saSrv, sizeof(pConn->srvsaListen));

    LOG(X_DEBUG("Accepted connection on port %d from %s:%d"), htons(INET_PORT(pListenCfg->sa)), 
        FORMAT_NETADDR(sdclient.sa, tmp, sizeof(tmp)), htons(INET_PORT(sdclient.sa)));

    pthread_attr_init(&pConn->attr);
    pthread_attr_setdetachstate(&pConn->attr, PTHREAD_CREATE_DETACHED);
    memset(&pConn->sd.netsocket, 0, sizeof(pConn->sd.netsocket));
    NETIO_SET(pConn->sd.netsocket, sdclient.netsocket);
    memcpy(&pConn->sd.sa, &sdclient.sa, INET_SIZE(sdclient));
    pConn->pListenCfg = pListenCfg;
    NETIOSOCK_FD(sdclient.netsocket) = INVALID_SOCKET;

    wrapArg.thread_func = thread_func;
    wrapArg.pConnPool = pListenCfg->pConnPool;
    wrapArg.pConn = pConn;
    wrapArg.flags = 1;
    wrapArg.tid_tag[0] = '\0';
    if((s = logutil_tid_lookup(pthread_self(), 0)) && s[0] != '\0') {
      snprintf(wrapArg.tid_tag, sizeof(wrapArg.tid_tag), "%s-%u", s, pConn->pool.id);
    }
    //wrapArg.pcond = &cond;

  //fprintf(stderr, "%d CALLING wrap: 0x%x pConn:0x%x\n", pthread_self(), &wrapArg, wrapArg.pConn);

    if((rc = pthread_create(&pConn->ptd,
                    &pConn->attr,
                    (void *) thread_func_wrapper,
                    (void *) &wrapArg)) != 0) {
      LOG(X_ERROR("Unable to create connection handler thread on port %d from %s:%d (%d %s)"), 
          htons(INET_PORT(pListenCfg->sa)), FORMAT_NETADDR(sdclient.sa, tmp, sizeof(tmp)),
          htons(INET_PORT(sdclient.sa)), rc, strerror(rc));
      netio_closesocket(&pConn->sd.netsocket);
      pool_return(pListenCfg->pConnPool, &pConn->pool);
      wrapArg.flags = 0;
      //pthread_cond_broadcast(&cond);
      break;
    }

    pthread_attr_destroy(&pConn->attr);

    //
    // be careful not to reuse the same wrapArg instance 
    // since the stack variable arguments could get
    // overwritten by the next loop iteration, before the thread proc is 
    // invoked
    //
    //fprintf(stderr, "wait start\n");
    tv0 = timer_GetTime();
    //if(wrapArg.flags == 1) {

      //
      // It seems that calling pthread_cond_wait here to check if the thread creation is
      // complete is not completely reliable and portable, so we do the lame way 
      // of sleeping and polling.
      //
      //pthread_cond_wait(&cond, &mtx);

      while(wrapArg.flags == 1) {
        usleep(100);
        if(((tv1 = timer_GetTime()) - tv0) / TIME_VAL_MS > 1000) {
          LOG(X_WARNING("Abandoning wait for connection thread start on port %d from %s:%d"),
               htons(INET_PORT(pListenCfg->sa)),
              FORMAT_NETADDR(pListenCfg->sa, tmp, sizeof(tmp)), ntohs(INET_PORT(pListenCfg->sa)));
          break;
        } 
      }
      //fprintf(stderr, "THREAD STARTED AFTER %lld ns\n", (timer_GetTime() - tv0));
    //}

    //fprintf(stderr, "wait done\n");

    //while(wrapArg.flag == 1) {
    //  usleep(10000); 
    //}

  }

  //pthread_cond_destroy(&cond);
  pthread_mutex_destroy(&mtx);

  return rc;
}
Exemplo n.º 5
0
int rtmp_auth_cache_store(RTMP_AUTH_PERSIST_STORAGE_T *pcachedAuth, const RTMP_AUTH_PERSIST_T *pElem) {
  int rc = -1;
  unsigned int sz = 0;
  TIME_VAL tm;
  RTMP_AUTH_PERSIST_NODE_T *p, *p_prev = NULL;
  RTMP_AUTH_PERSIST_NODE_T *pinsert = NULL;
  RTMP_AUTH_PERSIST_NODE_T *poldest = NULL;

  if(pElem->opaque[0] == '\0') {
    return -1;
  }

  VSX_DEBUG_RTMP( LOG(X_DEBUG("RTMP auth cache storing opaque: '%s', salt: '%s', challenge: '%s'"), 
                             pElem->opaque, pElem->salt, pElem->challenge); );

  tm = timer_GetTime();

  pthread_mutex_lock(&pcachedAuth->mtx);

  p = pcachedAuth->phead;
  while(p) {

    if(p->tm == 0 || !strcmp(pElem->opaque, p->s.opaque) || 
       p->tm + (RTMP_AUTH_CACHE_LIFETIME_SEC * TIME_VAL_US) < tm) {
      pinsert = p;
      break;
    }
    if(!poldest || poldest->tm > p->tm) {
      poldest = p;
    }
Exemplo n.º 6
0
int stream_udp(STREAM_XMIT_NODE_T *pList, double durationSec) {
  STREAM_XMIT_NODE_T *pStream;
  COLLECT_STREAM_PKTDATA_T collectPkt;
  int triedXmit;
  unsigned int idxDest;
  TIME_VAL tmstart, tm1, tmnow;
  TIME_VAL tmprevbwdescr;
  int rc;
  int sz;
  int szPkt;
  unsigned int szData;
  const unsigned char *pData;
  unsigned int szDataPayload;
  const unsigned char *pDataPayload;
  uint64_t totBytes = 0;
  unsigned int totPkts = 0;
  unsigned int bytes = 0;
  unsigned int pkts = 0;
  unsigned int bytes2 = 0;
  unsigned int pkts2 = 0;
  //char dstStr[64];
#ifndef WIN32
  unsigned int countIterations = 0;
#endif // WIN32

  if(!pList 
#if defined(VSX_HAVE_LICENSE)
   || !pList->pLic
#endif // VSX_HAVE_LICENSE
     ) {
    return -1;
  }

  //snprintf(dstStr, sizeof(dstStr), "%s:%d", inet_ntoa(pList->pRtpMulti->pdests[0].saDsts.sin_addr), 
  //            ntohs(pList->pRtpMulti->pdests[0].saDsts.sin_port));

  tmstart = tmnow = timer_GetTime();
  tm1 = tmstart;
  tmprevbwdescr = tmstart;


  while(*pList->prunning == STREAMER_STATE_RUNNING && !g_proc_exit) {

    pStream = pList;
    triedXmit = 0;

    while(pStream) {

      if((rc = pStream->cbCanSend(pStream->pCbData)) > 0) {

        pData = stream_rtp_data(pStream->pRtpMulti);
        szData = stream_rtp_datalen(pStream->pRtpMulti);

        if(szData >= RTP_HEADER_LEN) {
          pDataPayload = pData + RTP_HEADER_LEN;
          szDataPayload = szData - RTP_HEADER_LEN;
        } else {
          pDataPayload = NULL;
          szDataPayload = 0;
        }

        if(pStream->pXmitAction->do_stream) {
          triedXmit = 1;

          totPkts++;
          pkts++;
          pkts2++;

          if(pStream->pXmitAction->do_output) {

            szPkt = 0;
            for(idxDest = 0; idxDest < pStream->pRtpMulti->numDests; idxDest++) {
  
              if(pStream->pXmitDestRc[idxDest] != 0) {
                continue;
              }
              if(pStream->rawSend) {
                if(pktgen_Queue(pData, szData) != 0) {
                  pStream->pXmitDestRc[idxDest] = -1; 
                  sz = -1;
                } else {
                  sz = szData;
                }
              } else {

                //
                // Check and send an rtcp sender report
                //
                if(*pStream->pfrtcp_sr_intervalsec > 0 &&
                  (tmnow - pStream->pRtpMulti->pdests[idxDest].tmLastRtcpSr) / TIME_VAL_MS  > 
                         *pStream->pfrtcp_sr_intervalsec * 1000) {
                  sendRtcpSr(pStream, idxDest);
                  pStream->pRtpMulti->pdests[idxDest].tmLastRtcpSr = tmnow;
                } 

                if((sz = sendPktUdpRtp(pStream, idxDest, pData, szData)) < 0) {
                  pStream->pXmitDestRc[idxDest] = sz; 
                }
              }
              if(szPkt == 0 && sz > 0) {
                szPkt = sz; 
              }
            } // end of for

            // Exit if there are no good transmitters in the list
            if(pStream->pXmitAction->do_output && szPkt == 0) {
              return -1;
            }

          } else {    // if do_output
            szPkt = szData;
          }

          if(!pStream->pXmitAction->do_output_rtphdr && szPkt > RTP_HEADER_LEN) {
            szPkt -= RTP_HEADER_LEN;
          }

          totBytes += szPkt;
          bytes += szPkt;

          //
          // Add the packet data to any outbound avclive subscribers
          //
          // TODO: do not hardcode szData > RTP_HEADER_LEN rtp hdr len
          if(pStream->pLiveQ && pStream->pLiveQ->numActive > 0 && szDataPayload > 0) {
            pthread_mutex_lock(&pStream->pLiveQ->mtx);
            for(sz = 0; (unsigned int) sz < pStream->pLiveQ->max; sz++) {
              if(pStream->pLiveQ->pQs[sz]) {
                pktqueue_addpkt(pStream->pLiveQ->pQs[sz], pDataPayload, szDataPayload, NULL, 0);
              }
            }
            pthread_mutex_unlock(&pStream->pLiveQ->mtx);
          }
          bytes2 += szPkt;

        } else {

          // preserve rtp sequence number during 'live pause'
          //pStream->pRtp->m_pRtp->sequence_num = 
          //  htons(htons(pStream->pRtp->m_pRtp->sequence_num) - 1);

          //During 'live pause', update the last seq #
          //if(pStream->pXmitAction->prior_do_stream && pStream->prtp_sequence_at_end) {
          //  *pStream->prtp_sequence_at_end = pStream->pRtp->m_pRtp->sequence_num;
          //}
          //fprintf(stderr, "not streaming\n");

        }

        //
        // Record output stream
        //
        if(pStream->pXmitAction->do_record_post && pStream->pXmitCbs->cbRecord && 
           pStream->pXmitCbs->pCbRecordData) {

          memset(&collectPkt, 0, sizeof(collectPkt));
          collectPkt.payload.pData = (unsigned char *) pDataPayload;
          PKTCAPLEN(collectPkt.payload) = szDataPayload;
          if((sz = pStream->pXmitCbs->cbRecord(pStream->pXmitCbs->pCbRecordData, &collectPkt)) < 0) {
            return -1;
          }
          if(triedXmit == 0) {
            triedXmit = 1;
          }
        }

        //
        // Call post processing function, such as http live streaming
        // callback to segment and package output ts files 
        //
        if(pStream->pXmitAction->do_httplive && pStream->pXmitCbs->cbPostProc &&
           pStream->pXmitCbs->pCbPostProcData && pStream->pXmitAction->do_stream) {

          if((sz = pStream->pXmitCbs->cbPostProc(pStream->pXmitCbs->pCbPostProcData, 
                                                pDataPayload, szDataPayload)) < 0) {
            return -1;
          }
          if(triedXmit == 0) {
            triedXmit = 1;
          }
        }


        //if(pStream->pXmitAction->do_stream != pStream->pXmitAction->prior_do_stream) {
        //  pStream->pXmitAction->prior_do_stream = pStream->pXmitAction->do_stream;
        //}


        pStream->pRtpMulti->payloadLen = 0;

        if((rc = pStream->cbPreparePkt(pStream->pCbData)) < 0) {
          return -1;
        }
        //fprintf(stderr, "streamer prepare pkt returned %d\n", rc);

      } else if(rc < 0) {
        LOG(X_DEBUG("Stream ending, sent: %"LL64"u bytes %u pkts"), totBytes, totPkts); 
        return -1;
      } else {
        //fprintf(stderr, "streamer cansend rc:%d\n", rc);
      } 

      pStream = pStream->pNext;
    } // while(pStream)

    pktgen_SendQueued();


    if(triedXmit == 0) {

#ifdef WIN32

      //sl1 = timer_GetTime();

      //Sleep(1) may sleep past its short bedtime on win32, even from a thread w/ SCHED_RR
      //However, sleep(0) uses alot more cpu slices
      //TODO: make this a WaitForSingleObject for any registered pktqueue writers
      

      if(pList->pSleepQ) {
        //TODO: this does not return if a pkt has been queued and no subsequent pkt arrives
        pktqueue_waitforunreaddata(pList->pSleepQ);
        //pthread_cond_wait(pList->pCond, pList->pMtxCond);
      } else {
        Sleep(1);
      }

    } else {
      // On windows Sleep 0 relinquishes execution for any waiting threads
      Sleep(0);

#else // WIN32

      VSX_DEBUG2(tmnow = timer_GetTime())

      usleep(1000);
      countIterations = 0;

      VSX_DEBUGLOG3("stream_udp slept for %lld ns\n", timer_GetTime() - tmnow);

    } else {

      if(countIterations++ > 10000) {
        // During continuous xmit, sleep to prevent unresponsive system
        usleep(1);
        countIterations = 0;
      } 
#endif // WIN32

    } 

    tmnow = timer_GetTime();

    if(pList->pBwDescr && (tmnow / TIME_VAL_US) > (tmprevbwdescr / TIME_VAL_US) + 1) {
      pList->pBwDescr->intervalMs = (float)(tmnow - tmprevbwdescr)/ TIME_VAL_MS;
      pList->pBwDescr->pkts = pkts2;
      pList->pBwDescr->bytes = bytes2;
      TV_FROM_TIMEVAL(pList->pBwDescr->updateTv, tmnow);
      //pList->pBwDescr->updateTv.tv_sec = tmnow / TIME_VAL_US;
      //pList->pBwDescr->updateTv.tv_usec = tmnow % TIME_VAL_US;
      bytes2 = 0;
      pkts2 = 0;
      tmprevbwdescr = tmnow;
    }

    if(durationSec > 0 && tmnow > tmstart + (durationSec * TIME_VAL_US)) {
      LOG(X_DEBUG("Stream duration %.1f sec limit reached"), durationSec);
      *pList->prunning = STREAMER_STATE_FINISHED;
    }

#if defined (VSX_HAVE_LICENSE)
    // Check if stream time is limited
    if(!(pList->pLic->capabilities & LIC_CAP_STREAM_TIME_UNLIMITED)) {
      if(tmnow > tmstart + (STREAM_LIMIT_SEC * TIME_VAL_US)) {
        LOG(X_INFO("Stream time limited.  Stopping stream transmission after %d sec"), 
                 (int) (tmnow - tmstart) / TIME_VAL_US);
        *pList->prunning = STREAMER_STATE_FINISHED;
        if(!(g_proc_exit_flags & PROC_EXIT_FLAG_NO_EXIT_ON_STREAM_TIME_LIMITED)) {
          g_proc_exit = 1;
        }
      }
    }
#endif // VSX_HAVE_LICENSE

#if defined(LITE_VERSION)
    if(tmnow > tmstart + (STREAM_LIMIT_LITE_SEC * TIME_VAL_US)) {
      LOG(X_INFO("Stream time limited.  Stopping stream transmission after %d sec"),
               (int) (tmnow - tmstart) / TIME_VAL_US);
      *pList->prunning = STREAMER_STATE_FINISHED;
      if(!(g_proc_exit_flags & PROC_EXIT_FLAG_NO_EXIT_ON_STREAM_TIME_LIMITED)) {
        g_proc_exit = 1;
      }
    }
#endif // (LITE_VERSION)

/*
    if(0 && pList->verbosity > 1 && tv2.tv_sec > tv1.tv_sec+3) {

      elapsedMs0 = ((tv2.tv_sec - tv0.tv_sec) * 1000) + 
                   ((tv2.tv_usec - tv0.tv_usec) /1000);
      elapsedMs1 = ((tv2.tv_sec - tv1.tv_sec) * 1000) + 
                   ((tv2.tv_usec - tv1.tv_usec) /1000);

      fprintf(stdout, "%u", elapsedMs0/1000);
         
      if(durationSec != 0) {
        fprintf(stdout, "/%.1f", durationSec);
      }

      fprintf(stdout, " sec, %s %.1fKb/s %.1fpkts/s (total: %u pkts, %.1fKB, %.1fKb/s)",
           dstStr,
           (double)(bytes  / 128.0f / ((double)elapsedMs1/1000.0f)),
           (double)(pkts/ ((double)elapsedMs1/1000.0f)),
                         totPkts, (double)totBytes/1024.0f,
                           (double)(totBytes /  128.0f / ((double)elapsedMs0/1000.0f))); 
      fprintf(stdout, "\n");

      bytes = 0;
      pkts = 0;
      tv1.tv_sec = tv2.tv_sec;
      tv1.tv_usec = tv2.tv_usec;
    }
 */  
  }
Exemplo n.º 7
0
static void logger_write_file(LOG_PROPERTIES_T *pLogProperties, int sev, 
                              const char *msg, va_list *pvlist) {

  struct tm *ptm = NULL;
  char strtime[64];
  char strpid[64];
  char strsev[30];
  char strspace[2];
  const TIME_VAL tmNowUs = timer_GetTime();
  const time_t tmNow = tmNowUs / TIME_VAL_US;
  //const time_t tmNow = time(NULL);

  if(!pLogProperties->g_fp ||
    !(pLogProperties->g_log_flags & LOG_FLAG_USEFILEOUTPUT) ||
     sev == 0 ||
    (sev > 0 && sev > pLogProperties->g_log_level) ||
    (sev < 0 && sev < (-1 * pLogProperties->g_log_level))) {
    return;
  }

  if((pLogProperties->g_log_flags & LOG_OUTPUT_PRINT_DATE) &&
    (ptm = (struct tm *) localtime(&tmNow)) != NULL) {
    strftime(strtime, sizeof(strtime) -1, "%b %d %H:%M:%S", ptm);
    strtime[sizeof(strtime) - 1] = '\0';
  } else {
    strtime[0] = '\0';
  }

  strpid[0] = '\0';
  print_tag(pLogProperties, strpid, sizeof(strpid));

  if(pLogProperties->g_log_flags & LOG_OUTPUT_PRINT_SEV) {
    snprintf(strsev, sizeof(strsev) - 1, "%s ", logger_getSeverityStr((unsigned short) sev));
    strsev[sizeof(strsev) - 1] = '\0';
  } else {
    strsev[0] = '\0';
  }

  if(strtime[0] != '\0' || (strpid[0] != '\0' && strsev[0] != '\0')) {
    strspace[0] = ' ';
    strspace[1] = '\0';
  } else {
    strspace[0] = '\0';
  }

  // Log to output file
  fprintf(pLogProperties->g_fp, "%s.%.3llu %s%s%s", strtime, 
          tmNowUs/TIME_VAL_MS%TIME_VAL_MS, strsev, strpid, strspace);
  vfprintf(pLogProperties->g_fp, msg, *pvlist);

  // flush output
  if(pLogProperties->g_log_flags & LOG_FLAG_FLUSHOUTPUT) {

    if(pLogProperties->g_fp != NULL &&
       (pLogProperties->g_log_flags & LOG_FLAG_USEFILEOUTPUT)) {
      fflush(pLogProperties->g_fp);
    }
  }

  return;
}
Exemplo n.º 8
0
static int readFramesFromDev(CAP_DEV_CFG_T *pCapDevCfg) {
  int rc = 0;
  TIME_VAL tv0, tv, tvSleep, tvStart;
  TIME_VAL tvElapsed = 0;
  TIME_VAL tvMark = 0;
  unsigned int frameIdx = 0;
  COLLECT_STREAM_PKTDATA_T pktdata;
  CAP_DEV_CTXT_T capDevCtxt;
  CAPTURE_FILTER_T *pFilter = &pCapDevCfg->pCapCfg->pcommon->filt.filters[pCapDevCfg->idxFilter];
  //BMP_FILE_T bmp;

  //memset(&bmp, 0, sizeof(bmp));
  memset(&capDevCtxt, 0, sizeof(capDevCtxt));
  capDevCtxt.dev = pCapDevCfg->pCapCfg->pcommon->localAddrs[pCapDevCfg->idxFilter];
  //capDevCtxt.dev = "./rawfmt.bmp";
  if(readFramesSetup(pFilter, &capDevCtxt.frame) < 0) {
    return -1;
  }

  //TODO: seperate out and maintain better throttle mechanism

  tv0 = tvStart = timer_GetTime();
  while(!g_proc_exit && pCapDevCfg->pCapCfg->running == 0) {

    //
    // Reading too slow, reset time reference
    //
    if(tvElapsed > tvMark + 300000) {
      LOG(X_WARNING("Resetting read time for %s after %llu ms > %llu ms (%.3ffps x %ufr)"),
        capDevCtxt.dev, tvElapsed / TIME_VAL_MS, 
        (TIME_VAL)((1000.0f / pFilter->fps) * frameIdx), pFilter->fps, frameIdx); 
      tv0 = timer_GetTime();
      frameIdx = 0;
    }    

    do {
      tv = timer_GetTime();
      tvElapsed = (tv - tv0);
      tvMark = (frameIdx / pFilter->fps) * TIME_VAL_US;

      if(tvElapsed < tvMark) {
        if((tvSleep = (tvMark - tvElapsed)) < 1000) {
          tvSleep = 1;
        }
        //fprintf(stderr, "sleeping %lld ns\n", tvSleep);
        usleep(tvSleep);
        tv = timer_GetTime();
        tvElapsed = (tv - tv0);
      }

    } while(tvElapsed < tvMark);

//if(frameIdx > 50) usleep(50000);
     

    //fprintf(stderr, "reading frame %d supposed to be:%lld  at:%lld\n", frameIdx, (TIME_VAL) (frameIdx*1000.0f/pFilter->fps),(timer_GetTime() - tv0)/ TIME_VAL_MS);

    if((rc = readFrameFromDev(&capDevCtxt)) < 0) {
      break;
    }

/*
    if((rc = bmp_create(&bmp, pFilter->mediaType,
               pFilter->width, pFilter->height,
               capDevCtxt.frame.pData)) < 0) {
      LOG(X_ERROR("Failed to create bmp %d x %d for format %d"), 
           pFilter->width, pFilter->height, pFilter->mediaType);
      break;
    }
    PKTLEN32(pktdata.payload) = BMP_GET_LEN(&bmp);
    pktdata.payload.pData = BMP_GET_DATA(&bmp);
*/

    pktdata.tv.tv_sec = (tv - tvStart) / TIME_VAL_US;
    pktdata.tv.tv_usec = (tv - tvStart) % TIME_VAL_US;
    PKTLEN32(pktdata.payload) = capDevCtxt.frame.len;
    pktdata.payload.pData = capDevCtxt.frame.pData;

    //fprintf(stderr, "got %d  bmp %d from %s %llu\n", capDevCtxt.frame.len, BMP_GET_LEN(&bmp), capDevCtxt.dev, tv - tvStart);

    pCapDevCfg->pStream->cbOnPkt(&pCapDevCfg->pStreamCbData->sp[0],
                                 (const COLLECT_STREAM_PKTDATA_T *) &pktdata);

    frameIdx++;
  }

  if(capDevCtxt.fd > 0) {
    close(capDevCtxt.fd);
  }
  free(capDevCtxt.frame.pBuf);
  //bmp_destroy(&bmp);

  return rc;
}
Exemplo n.º 9
0
int sys_cpu_usage(SYS_USAGE_CTXT_T *pCtxt) {
  int rc = 0;
  CPU_SNAPSHOT_T *pSnapshots[2];
  CPU_SNAPSHOT_T diff;
  TIME_VAL tmnow;

  if(!pCtxt || !pCtxt->pcurC) {
    return -1;
  }

  if(pCtxt->cpusnapshots[0].tvsnapshot == 0) {
    pSnapshots[0] = &pCtxt->cpusnapshots[0];
    pSnapshots[1]  = &pCtxt->cpusnapshots[1];
  } else {
    pSnapshots[1] = &pCtxt->cpusnapshots[0];
    pSnapshots[0]  = &pCtxt->cpusnapshots[1];
  }

  tmnow = timer_GetTime();

  //
  // Return if it has not yet been SYS_CPU_MIN_INTERVAL_MS since the last snapshot
  //
  if(pSnapshots[1]->tvsnapshot != 0 && 
     ((tmnow - pSnapshots[1]->tvsnapshot) / TIME_VAL_MS) < SYS_CPU_MIN_INTERVAL_MS) {
    LOG(X_DEBUGV("CPU snapshots not ready"));
    return 0;
  }
 
  //
  // Take a running snapshot of the cpu counters
  //
  if((rc = cpu_snapshot(pSnapshots[0])) < 0) {
    return rc;
  } 

  pSnapshots[0]->tvsnapshot = tmnow;

  if(pSnapshots[1]->tvsnapshot == 0) {
    //
    // We've only been called once and don't have at least 2 snapshots
    //
    return 0;
  }

  //
  // Make sure the counters have been updated since the last snapshot
  //
  if((diff.tmtot = pSnapshots[0]->tmtot - pSnapshots[1]->tmtot) == 0) {
    LOG(X_ERROR("CPU tmtot 0 (%Lf - %Lf)"), pSnapshots[0]->tmtot, pSnapshots[1]->tmtot);
    return 0;
  }

  diff.tmuser = pSnapshots[0]->tmuser - pSnapshots[1]->tmuser;
  diff.tmnice = pSnapshots[0]->tmnice - pSnapshots[1]->tmnice;
  diff.tmsys = pSnapshots[0]->tmsys - pSnapshots[1]->tmsys;
  diff.tmidle = pSnapshots[0]->tmidle - pSnapshots[1]->tmidle;

  pCtxt->pcurC->percentuser = get_percentage(diff.tmuser, &diff);
  pCtxt->pcurC->percentnice = get_percentage(diff.tmnice, &diff);
  pCtxt->pcurC->percentsys = get_percentage(diff.tmsys, &diff);
  pCtxt->pcurC->percentidle = get_percentage(diff.tmidle, &diff);

  pSnapshots[1]->tvsnapshot = 0;

  return 1;
}
Exemplo n.º 10
0
int streamxmit_onRTCPNACK(STREAM_RTP_DEST_T *pDest, const RTCP_PKT_RTPFB_NACK_T *pNack) {
  STREAMXMIT_PKT_HDR_T *pktHdr;
  TIME_VAL tvNow;
  uint16_t nackSeqNumStart;
  uint16_t nackBlp;
  unsigned int seqNumOffset;
  unsigned int idxWr;
  unsigned int count = 0;
  int doRetransmission = 0;
  STREAM_XMIT_QUEUE_T *pAsyncQ = NULL;

  if(!pDest || !pNack) {
    return -1;
  } else if(!(pAsyncQ = &pDest->asyncQ) || !pAsyncQ->doRtcpNack || !pAsyncQ->pQ) {
    return 0;
  }

//TODO: compute incoming NACK rate to outgoing RTP rate for ABR algorithm

  tvNow = timer_GetTime();
  nackSeqNumStart = htons(pNack->pid);
  nackBlp = htons(pNack->blp);

  pthread_mutex_lock(&pAsyncQ->mtx);

  //LOG(X_DEBUG("streamxmit_onRTCPNACK nackSeqNumStart:%d"), nackSeqNumStart);
  //fprintf(stderr, "treamxmit_onRTCPNACK nackSeqNumStart... nackSeqNumStart:%d\n", nackSeqNumStart); pktqueue_dump(pDest->asyncQ.pQ,  pktqueue_cb_streamxmit_dump_pkthdr);

  //
  // If the highest possible NACK sequence num came before the first packet of the keyframe of the current GOP,
  // then disregard it because we are assuming the keyframe is an IDR.
  //
  if(pAsyncQ->haveLastKeyframeSeqNumStart && nackSeqNumStart + 16 < pAsyncQ->lastKeyframeSeqNumStart) {
    pthread_mutex_unlock(&pAsyncQ->mtx);
    LOG(X_DEBUG("RTP NACK for sequence: %d ignored because it pertains to a prior GOP sequence:%d"), nackSeqNumStart, 
                pDest->asyncQ.lastKeyframeSeqNumStart);
    return 0;
  }

  //
  // Iterate the stored packet list backwards starting with the most recently 
  // transmitted packet
  //
  idxWr = pAsyncQ->pQ->idxWr;
  //LOG(X_DEBUG("streamxmit_onRTCPNACK starting at idxWr:%d / %d"), idxWr-1, pAsyncQ->pQ->cfg.maxPkts);
  while(count++ < pAsyncQ->pQ->cfg.maxPkts) {

    if(idxWr > 0) {
      idxWr--;
    } else {
      idxWr = pAsyncQ->pQ->cfg.maxPkts - 1;
    }

    if(!(pAsyncQ->pQ->pkts[idxWr].flags & PKTQUEUE_FLAG_HAVEPKTDATA)) {
      //
      // The write queue slot is empty
      //
      //LOG(X_DEBUG("streamxmit_onRTCPNACK idxWr:%d / %d is empty.. break"), idxWr, pAsyncQ->pQ->cfg.maxPkts);
      break;

    } else if((pktHdr = (STREAMXMIT_PKT_HDR_T *) pAsyncQ->pQ->pkts[idxWr].xtra.pQUserData) && !pktHdr->rtcp) {

      if(pktHdr->seqNum < nackSeqNumStart) {

        //
        // 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
        //
        //LOG(X_DEBUG("streamxmit_onRTCPNACK idxWr:%d / %d is empty.. break.. seqNuM:%d came before nackSeqNumStart:%d"), idxWr, pAsyncQ->pQ->cfg.maxPkts, pktHdr->seqNum, nackSeqNumStart);
        break;

      } else if(pktHdr->tvXmit + (pAsyncQ->nackHistoryMs * TIME_VAL_MS) < tvNow) {

        //
        // The queue slot packet time is too old and beyond our threshold for RTP retransmission
        //
        //LOG(X_DEBUG("streamxmit_onRTCPNACK idxWr:%d / %d is empty.. seqNuM:%d nack too old to honor"), idxWr, pAsyncQ->pQ->cfg.maxPkts, pktHdr->seqNum);
        if(pktHdr->doRetransmit >= 0) {
          LOG(X_DEBUG("RTP NACK for sequence: %d ignored because it has age %d ms > %d ms"), nackSeqNumStart, pAsyncQ->nackHistoryMs,
               (tvNow - pktHdr->tvXmit) / TIME_VAL_MS);
        }
        pktHdr->doRetransmit = -1;
        break;

//TODO: handle seq roll... should not be a big problem here...
      } else if(pktHdr->doRetransmit >= 0 && pktHdr->seqNum <= nackSeqNumStart + 16) {

        //LOG(X_DEBUG("streamxmit_onRTCPNACK idxWr:%d / %d seqNum:%d, nackSeqNumStart:%d is within range. seqNumOffset:%d, nackBlp:0x%x"), idxWr, pAsyncQ->pQ->cfg.maxPkts, pktHdr->seqNum, nackSeqNumStart, (pktHdr->seqNum - nackSeqNumStart), nackBlp);

        if((seqNumOffset = pktHdr->seqNum - nackSeqNumStart) == 0 || (nackBlp & (1 << (seqNumOffset - 1)))) {

          //
          // The packet sequence number matches a packet which is being negatively-acknowledged so mark
          // it for retransmission
          //
          if(pktHdr->doRetransmit >= 0 && 
             (!pAsyncQ->haveLastKeyframeSeqNumStart || pktHdr->seqNum >= pAsyncQ->lastKeyframeSeqNumStart)) {

            LOG(X_DEBUGV("RTP NACK marked pt:%d sequence:%d for retransmission"), 
                pDest->pRtpMulti->init.pt, pktHdr->seqNum);

            if(pktHdr->doRetransmit == 0) {

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

            }

            pktHdr->doRetransmit++;

          } else {
            LOG(X_DEBUG("RTP NACK not marking pt:%d sequence:%d for retransmission"), pDest->pRtpMulti->init.pt, pktHdr->seqNum);
          }


       
          doRetransmission = 1;
        }

      }
    }

  }

  if(doRetransmission) {
    if(!pAsyncQ->haveRequestedRetransmission) {
      pAsyncQ->haveRequestedRetransmission = 1;
      //
      // Signal the output retransmission thread
      //
      vsxlib_cond_signal(&pDest->pRtpMulti->asyncRtpCond.cond, &pDest->pRtpMulti->asyncRtpCond.mtx);
    }
  }

  pthread_mutex_unlock(&pAsyncQ->mtx);

  return 0;
}
Exemplo n.º 11
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.º 12
0
int streamxmit_sendto(STREAM_RTP_DEST_T *pDest, const unsigned char *data, unsigned int len, 
                      int rtcp, int keyframe, int drop) {
  int rc = 0;
  NETIO_SOCK_T *pnetsock = NULL;
  const unsigned char *pData = data;
  PKTQ_EXTRADATA_T qXtra;
  STREAMXMIT_PKT_HDR_T pktHdr;
  unsigned char encBuf[PACKETGEN_PKT_UDP_DATA_SZ];

  //
  // If we're using DTLS-SRTP over audio/video mux (on same RTP port) then we need to choose
  // the right socket which has completed the DTLS handshake
  //
  if(rtcp) {
    pnetsock = STREAM_RTCP_PNETIOSOCK(*pDest);
  } else {
    pnetsock = STREAM_RTP_PNETIOSOCK(*pDest);
  }

  //LOG(X_DEBUG("STREAMXMIT_SENDTO len:%d, rtcp:%d, drop:%d, pDest: 0x%x, srtp:0x%x, pSrtpShared: 0x%x, 0x%x, lenK:%d"), len, rtcp, drop, pDest, &pDest->srtps[rtcp ? 1 : 0], pDest->srtps[rtcp ? 1 : 0].pSrtpShared, SRTP_CTXT_PTR(&pDest->srtps[rtcp ? 1 : 0]), SRTP_CTXT_PTR(&pDest->srtps[rtcp ? 1 : 0])->k.lenKey);LOGHEX_DEBUG(data, MIN(16, len));

  if((rc = srtp_dtls_protect(pnetsock, data, len, encBuf, sizeof(encBuf),
                      (const struct sockaddr *) (rtcp ? &pDest->saDstsRtcp : &pDest->saDsts), 
                      pDest->srtps[rtcp ? 1 : 0].pSrtpShared,
                      rtcp ? SENDTO_PKT_TYPE_RTCP : SENDTO_PKT_TYPE_RTP)) < 0) {
    if(rc == -2) {
      // DTLS handshake not complete
      return 0;
    } else {
      return -1;
    }
  } else if(rc > 0) {
    pData = encBuf;
    len = rc;
  }

  //
  // Queue the packet for async sending
  //
  if(pDest->asyncQ.pQ && (pDest->asyncQ.doAsyncXmit || (!rtcp && pDest->asyncQ.doRtcpNack))) {

    memset(&qXtra, 0, sizeof(qXtra));
    memset(&pktHdr, 0, sizeof(pktHdr));
    pktHdr.flags = 0;
    pktHdr.tvCreate = timer_GetTime();
    if(!pDest->asyncQ.doAsyncXmit) {
      pktHdr.tvXmit = pktHdr.tvCreate;
    }
    if(!(pktHdr.rtcp = rtcp)) {
      pktHdr.seqNum = htons(pDest->pRtpMulti->pRtp->sequence_num);
      pktHdr.timeStamp = htonl(pDest->pRtpMulti->pRtp->timeStamp);
      pktHdr.keyframe = keyframe;
    }
    qXtra.pQUserData = &pktHdr;

    pthread_mutex_lock(&pDest->asyncQ.mtx);

    if(!pDest->asyncQ.isCurPktKeyframe && keyframe) {
      pDest->asyncQ.haveLastKeyframeSeqNumStart = 1;
      pDest->asyncQ.lastKeyframeSeqNumStart = pktHdr.seqNum;
      //LOG(X_DEBUG("NACK - GOP start at packet %d"), pktHdr.seqNum);
    }

    if(pktqueue_addpkt(pDest->asyncQ.pQ, pData, len, &qXtra,
       (!pDest->asyncQ.isCurPktKeyframe && keyframe ? 1 : 0)) != PKTQUEUE_RC_OK) {
      pthread_mutex_unlock(&pDest->asyncQ.mtx);
      return -1;
    }
    //LOG(X_DEBUG("NACK q rd:[%d]/%d, wr:%d"), pDest->asyncQ.pQ->idxRd, pDest->asyncQ.pQ->cfg.maxPkts, pDest->asyncQ.pQ->idxWr);
    pDest->asyncQ.isCurPktKeyframe = keyframe;

    pthread_mutex_unlock(&pDest->asyncQ.mtx);
    rc = len;

    //pktqueue_dump(pDest->asyncQ.pQ,  pktqueue_cb_streamxmit_dump_pkthdr);
  } 

  if(!pDest->asyncQ.doAsyncXmit && !drop) {
    if((rc = srtp_sendto(pnetsock, (void *) pData, len, 0, 
                         (const struct sockaddr *) (rtcp ? &pDest->saDstsRtcp : &pDest->saDsts), NULL, 
                         rtcp ? SENDTO_PKT_TYPE_RTCP : SENDTO_PKT_TYPE_RTP, 1)) < 0) {
      return -1;
    }

  } else if(drop) {
    rc = len;
  }

  if(pDest->pstreamStats) {
    stream_stats_addPktSample(pDest->pstreamStats, &pDest->streamStatsMtx, len, !rtcp);
  }

  return rc;
}
Exemplo n.º 13
0
int http_flv_recvloop(CAP_ASYNC_DESCR_T *pCfg,
                  unsigned int offset,
                  int sz, 
                  FILE_OFFSET_T contentLen,
                  unsigned char *pbuf,
                  unsigned int szbuf,
                  CAPTURE_STREAM_T *pStream) {

  CAP_HTTP_FLV_T ctxt;
  FLV_TAG_HDR_T *pTagHdr;
  unsigned char *pdata;
  unsigned int ts0 = 0;
  unsigned int ts;
  unsigned int tsoffset = 0;
  int havets0 = 0;
  TIME_VAL tm0, tm;
  unsigned int msElapsed;
  int do_sleep;
  int rc;

  memset(&ctxt, 0, sizeof(ctxt));
  ctxt.common.pCfg = pCfg;
  ctxt.common.pdata = pbuf;
  ctxt.common.dataoffset = offset;
  ctxt.common.datasz = offset + sz;
  ctxt.pStream = pStream;

  //if(sz > 0) {
  //  LOG(X_WARNING("Partial FLV HTTP Content-Header read offset %d not implemented. (offset:%d)"), sz, offset);
  //}

  if(net_setsocknonblock(NETIOSOCK_FD(pCfg->pSockList->netsockets[0]), 1) < 0) {
    return -1;
  }

  if(http_flv_init(&ctxt) < 0) {
    return -1;
  }

  //
  // Read 'FLV' 9 byte header
  //
  if(!(pdata = read_net_flv(&ctxt, 9))) {
    http_flv_close(&ctxt);
    return -1;
  }

  memcpy(&ctxt.flvhdr, pdata, 9);

  if(!(ctxt.flvhdr.type[0] == 'F' && ctxt.flvhdr.type[1] == 'L' && 
       ctxt.flvhdr.type[2] == 'V' && ctxt.flvhdr.ver == FLV_HDR_VER_1)) {
    LOG(X_ERROR("Invalid HTTP FLV start sequence 0x%x 0x%x 0x%x 0x%x"),
               pdata[0], pdata[1], pdata[2], pdata[3]); 
    http_flv_close(&ctxt);
    return -1;
  }

  if((FLV_HDR_HAVE_VIDEO((&ctxt.flvhdr)) && !ctxt.client.pQVid) ||
     (FLV_HDR_HAVE_AUDIO((&ctxt.flvhdr)) && !ctxt.client.pQAud)) {

    LOG(X_ERROR("FLV capture input queue(s) not propery configured: video: %d, audio: %d"),
                ctxt.client.pQVid ? 1 : 0, ctxt.client.pQAud ? 1 : 0);
    http_flv_close(&ctxt);
    return -1;
  }

  tm0 = timer_GetTime();

  if(pCfg->pcommon->caprealtime) {
    LOG(X_DEBUG("Treating capture as real-time."));
  }

  do {

    if(!(pTagHdr = (FLV_TAG_HDR_T *) read_net_flv(&ctxt, FLV_TAG_HDR_SZ))) {
      return -1;
    }

    ctxt.taghdr.szprev = htonl(pTagHdr->szprev);
    ctxt.taghdr.type = pTagHdr->type;
    memcpy(&ctxt.taghdr.size32, &pTagHdr->size, 3);
    ctxt.taghdr.size32 = htonl(ctxt.taghdr.size32 << 8);
    memcpy(&ctxt.taghdr.timestamp32, &pTagHdr->timestamp, 3);
    ctxt.taghdr.timestamp32 = htonl(ctxt.taghdr.timestamp32 << 8);
    ctxt.taghdr.timestamp32 |= (pTagHdr->tsext << 24);

    //
    // For live content, initial timestamp may not always begin at 0
    //
    if(!havets0) {
      if((ts0 = ctxt.taghdr.timestamp32) > 0) {
        havets0 = 1;
      }
    } else if(ctxt.taghdr.timestamp32 < ts0) {
      LOG(X_WARNING("HTTP FLV timestamp anamoly ts:%u, initial ts:%u (offset:%u)"),
          ctxt.taghdr.timestamp32, ts0, tsoffset);
      tsoffset += ts0;
      ts0 = ctxt.taghdr.timestamp32;
    }
    ts = ctxt.taghdr.timestamp32 - ts0 + tsoffset;

    //fprintf(stderr, "flv hdr type:0x%x sz:%d ts:%u(ts0:%u+%u) pkt_ts:%u\n", ctxt.taghdr.type, ctxt.taghdr.size32, ts, ts0, tsoffset, ctxt.taghdr.timestamp32);

    if(!(pdata = read_net_flv(&ctxt, ctxt.taghdr.size32))) {
      return -1;
    }

    //
    // For non-live content, throttle download rate inline with timestamps for real-time
    // restreaming
    //
    if(pCfg->pcommon->caprealtime) {
      do {
        do_sleep = 0;
        tm = timer_GetTime();
        msElapsed = (unsigned int) (tm - tm0) / TIME_VAL_MS;
//fprintf(stderr, "msElapsed:%d  ts:%d %lld %lld\n", msElapsed, ctxt.taghdr.timestamp32, tm, tm0);
        if(msElapsed < ts) {
          if((do_sleep = ts - msElapsed) > 500) {
            do_sleep = 500;
          }
//fprintf(stderr, "zzzz %d ms\n", do_sleep);
          usleep(do_sleep * 1000);
        }
      } while(do_sleep);
    }

    rc = 0;
    switch(ctxt.taghdr.type) {
      case FLV_TAG_VIDEODATA: 
        rc = rtmp_handle_vidpkt(&ctxt.client, pdata, ctxt.taghdr.size32, ts);
        break;
      case FLV_TAG_AUDIODATA: 
        rc = rtmp_handle_audpkt(&ctxt.client, pdata, ctxt.taghdr.size32, ts); 
      case FLV_TAG_SCRIPTDATA: 

        break;
      default:
        rc = -1;
        break;
    }

    if(rc < 0) {
      LOG(X_ERROR("Failed to process FLV packet type: 0x%x, len:%d"), 
                  ctxt.taghdr.type, ctxt.taghdr.size32);
      break;
    }


  } while(pCfg->running == 0 && 
          (contentLen == 0 || ctxt.client.ctxt.bytesRead < contentLen) &&
         !g_proc_exit);

  http_flv_close(&ctxt);

  return ctxt.client.ctxt.bytesRead;
}
Exemplo n.º 14
0
int streamer_run_tonet(STREAM_XMIT_NODE_T *pList, double durationSec) {
  STREAM_XMIT_NODE_T *pStream;
  int triedXmit;
  TIME_VAL tmstartOutput = 0;
  TIME_VAL tmstart, tmnow;
  int haveTmstartOutput = 0;
  int rc;

#if defined(VSX_HAVE_TURN)
  int pendingTurnRelays = 1;
  int pendingTurnRelays0;
  NET_PROGRESS_T progTurn;
  memset(&progTurn, 0, sizeof(progTurn));
#else // (VSX_HAVE_TURN)
  int pendingTurnRelays = 0;
#endif // (VSX_HAVE_TURN)

#if defined(VSX_HAVE_SSL_DTLS)
  TIME_VAL tmstartRtpHandshakeDone = 0;
  int giveupRtcpHandshakes = 0;
  int pendingDtlsRtpHandshakes = 1;
  NET_PROGRESS_T progRtp;
  NET_PROGRESS_T progRtcp;
  DTLS_TIMEOUT_CFG_T dtlsTimeouts;

  setDtlsTimeouts(&dtlsTimeouts, pList);
  memset(&progRtp, 0, sizeof(progRtp));
  memset(&progRtcp, 0, sizeof(progRtcp));
#else
  int pendingDtlsRtpHandshakes = 0;
#endif // (VSX_HAVE_SSL_DTLS)


#ifndef WIN32
  unsigned int countIterations = 0;
#endif // WIN32

  if(!pList 
#if defined(VSX_HAVE_LICENSE)
    || !pList->pLic
#endif // VSX_HAVE_LICENSE
    ) {
    return -1;
  }

  tmstart = tmnow = timer_GetTime();

  while(*pList->prunning == STREAMER_STATE_RUNNING && !g_proc_exit) {

    pStream = pList;
    triedXmit = 0;

    while(pStream) {

#if defined(VSX_HAVE_TURN)

      pendingTurnRelays0 = pendingTurnRelays;

      if(pendingTurnRelays > 0 && (pendingTurnRelays = do_turn_relays(pStream, &progTurn)) < 0) {
        LOG(X_ERROR("Giving up waiting for output transmission after TURN relay setup failure"));
        return -1; 
      }

      if(pendingTurnRelays == 0 && pendingTurnRelays0 != pendingTurnRelays && progTurn.numTotal > 0) {
        LOG(X_INFO("Starting output transmission after creating TURN relay(s)"));
      }

      //LOG(X_DEBUG("pendingTurnRelays:%d, %d/%d, numerror:%d"), pendingTurnRelays, progTurn.numCompleted, progTurn.numTotal, progTurn.numError); 
#endif // (VSX_HAVE_TURN)

#if defined(VSX_HAVE_SSL_DTLS)
      //if(pStream->pRtpMulti->pStreamerCfg->xcode.vid.pip.active) 
      //LOG(X_DEBUG("loop... pendingDtlsRtpHandshakes:%d, rtp:%d - %d, rtcp:%d - %d, giveupRtcpHandshakes:%d, tm:%lld ms"), pendingDtlsRtpHandshakes, progRtp.numTotal,  progRtp.numCompleted, progRtcp.numTotal,  progRtcp.numCompleted, giveupRtcpHandshakes, (timer_GetTime() - tmstart) / TIME_VAL_MS);

      //LOG(X_DEBUG("streamer2: pendingTurnRelays;%d, completed:%d/%d, pendingDtlsRtpHandshakes:%d"), pendingTurnRelays, progTurn.numCompleted, progTurn.numTotal, pendingDtlsRtpHandshakes);

      if(pendingTurnRelays == 0 && pendingDtlsRtpHandshakes > 0 && 
         (pendingDtlsRtpHandshakes = do_dtls_handshakes(pStream, tmstart, &tmstartRtpHandshakeDone, 
                                                     &progRtp, &progRtcp, &dtlsTimeouts)) < 0) {
        return -1;
      } else if(pendingDtlsRtpHandshakes == 0 && pendingTurnRelays == 0) {

        if(!haveTmstartOutput) {
          tmstartOutput = timer_GetTime();
          haveTmstartOutput = 1;
        }

        if(progRtcp.numTotal - progRtcp.numCompleted > 0 && !giveupRtcpHandshakes) {

          if(tmstartRtpHandshakeDone == 0) {
            tmstartRtpHandshakeDone = timer_GetTime();
          }

          if(((tmnow = timer_GetTime()) - tmstartRtpHandshakeDone) / TIME_VAL_MS > 
             dtlsTimeouts.handshakeRtcpAdditionalGiveupMs) {
            LOG(X_ERROR("Aborting DTLS RTCP handshaking after %lld ms"), (tmnow - tmstart) / TIME_VAL_MS);
            giveupRtcpHandshakes = 1;
          } else {
            do_dtls_handshakes(pStream, tmstart, &tmstartRtpHandshakeDone, NULL, &progRtcp, &dtlsTimeouts);
          }  

          //LOG(X_DEBUG("loop... calling do_dtls_handshakes Rtcp.numDtls:%d - Rtcp.numDtlsCompleted"), progRtcp.numTotal, progRtcp.numCompleted);
        }
#endif // (VSX_HAVE_SSL_DTLS)

        //if(pStream->pRtpMulti->pStreamerCfg->xcode.vid.pip.active) 
        //LOG(X_DEBUG("Calling cbCanSend"));
        if((rc = pStream->cbCanSend(pStream->pCbData)) > 0) {

          if((rc = pStream->cbPreparePkt(pStream->pCbData)) < 0) {
            return -1;
          } else if(rc > 0) {
            triedXmit = 1;
          }

        } else if(rc == -2) {
          // all programs have ended
          return 0;
        } else if(rc < 0) {
          return -1;
        } else {
          //fprintf(stderr, "streamer cansend rc:%d\n", rc);
        }   

#if defined(VSX_HAVE_SSL_DTLS)
      }
#endif // (VSX_HAVE_SSL_DTLS)

      pStream = pStream->pNext;
    } // while(pStream)

    if(triedXmit == 0) {

#ifdef WIN32

      //sl1 = timer_GetTime();

      //Sleep(1) may sleep past its short bedtime on win32, even from a thread w/ SCHED_RR
      //However, sleep(0) uses alot more cpu slices
      //TODO: make this a WaitForSingleObject for any registered pktqueue writers
      
      if(pList->pSleepQ) {
        //TODO: this does not return if a pkt has been queued and no subsequent pkt arrives
        pktqueue_waitforunreaddata(pList->pSleepQ);
      } else {
        Sleep(1);
      }

    } else {
      // On windows Sleep 0 relinquishes execution for any waiting threads
      Sleep(0);

#else // WIN32


      VSX_DEBUG2(tmnow = timer_GetTime());

      //fprintf(stderr, "usleep...\n");
      if(pendingDtlsRtpHandshakes > 0 || pendingTurnRelays > 0) {
        usleep(10000);
      } else {
        usleep(1000);
      }
      //fprintf(stderr, "usleep done...\n");

      countIterations = 0;

      VSX_DEBUG_STREAMAV( LOG(X_DEBUGV("stream_readframes slept for %lld ns"), timer_GetTime() - tmnow));

      //fprintf(stderr, "%lld --woke up from streamer2 zzz...\n", timer_GetTime() / TIME_VAL_MS);
    } else {
      //fprintf(stderr, "stream_readframes not sleeping count:%d tried:%d\n", countIterations, triedXmit);

      //fprintf(stderr, "no usleep...%d\n", countIterations);
      if(countIterations++ > 10000) {
        // During continuous xmit, sleep to prevent unresponsive system
        usleep(1);
        countIterations = 0;
      } 
#endif // WIN32

    } 

    tmnow = timer_GetTime();

#if defined(TEST_KILL)
//static int raiseSig=0; if(!raiseSig && haveTmstartOutput && tmnow > tmstartOutput + (4* TIME_VAL_US)) { raise(SIGINT); }
static int raiseSig=0; if(!raiseSig && haveTmstartOutput && tmnow > tmstartOutput + (19* TIME_VAL_US)) { g_proc_exit=1;if(g_proc_exit_cond){pthread_cond_broadcast(g_proc_exit_cond);} }
#endif // TEST_KILL

    if(haveTmstartOutput && durationSec > 0 && tmnow > tmstartOutput + (durationSec * TIME_VAL_US)) {
      LOG(X_DEBUG("Stream duration %.1f sec limit reached"), durationSec);
      //*pList->prunning = STREAMER_STATE_FINISHED;
      return 0;
    }

#if defined(VSX_HAVE_LICENSE)
    // Check if stream time is limited
    if(!(pList->pLic->capabilities & LIC_CAP_STREAM_TIME_UNLIMITED)) {

      if(haveTmstartOutput && tmnow > tmstartOutput + (STREAM_LIMIT_SEC * TIME_VAL_US)) {
        LOG(X_INFO("Stream time limited.  Stopping stream transmission after %d sec"), 
                 (int) (tmnow - tmstartOutput) / TIME_VAL_US);
        *pList->prunning = STREAMER_STATE_FINISHED;
        if(!(g_proc_exit_flags & PROC_EXIT_FLAG_NO_EXIT_ON_STREAM_TIME_LIMITED)) {
          g_proc_exit = 1;
        }
      }
    }
#endif // VSX_HAVE_LICENSE

/*
LOG(X_DEBUG("pList: 0x%x, pip.active:%d, overlay.havePip:%d"), pList, pList->pRtpMulti->pStreamerCfg->xcode.vid.pip.active,  pList->pRtpMulti->pStreamerCfg->xcode.vid.overlay.havePip);
if(pList->pRtpMulti->pStreamerCfg->xcode.vid.pip.active && haveTmstartOutput && tmnow > tmstartOutput + (5 * TIME_VAL_US)) {
  *pList->prunning = STREAMER_STATE_FINISHED;
  if(!(g_proc_exit_flags & PROC_EXIT_FLAG_NO_EXIT_ON_STREAM_TIME_LIMITED)) {
    g_proc_exit = 1;
  }
}
*/

#if defined(LITE_VERSION)
    if(haveTmstartOutput && tmnow > tmstartOutput + (STREAM_LIMIT_LITE_SEC * TIME_VAL_US)) {
      LOG(X_INFO("Stream time limited.  Stopping stream transmission after %d sec"),
               (int) (tmnow - tmstartOutput) / TIME_VAL_US);
      *pList->prunning = STREAMER_STATE_FINISHED;
      if(!(g_proc_exit_flags & PROC_EXIT_FLAG_NO_EXIT_ON_STREAM_TIME_LIMITED)) {
        g_proc_exit = 1;
      }
    }
#endif // (LITE_VERSION)

  }
Exemplo n.º 15
0
static int do_dtls_handshakes(STREAM_XMIT_NODE_T *pStream, 
                              TIME_VAL tmstart,
                              TIME_VAL *ptmstartRtpHandshakeDone,
                              NET_PROGRESS_T *progRtp, 
                              NET_PROGRESS_T *progRtcp,
                              const DTLS_TIMEOUT_CFG_T *pdtlsTimeouts) {
  int idxDest, idxDestPrior;
  STREAM_RTP_DEST_T *pDest = NULL;
  STREAM_RTP_DEST_T *pDestPrior = NULL;
  STREAM_RTP_MULTI_T *pRtpMulti = NULL;
  STREAM_RTP_MULTI_T *pRtpMultiPrior = NULL;
  int sameRtpSock, sameRtcpSock;
  TIME_VAL tmnow;

  //LOG(X_DEBUG("do_dtls_handshakes"));
  if(progRtp) {
    memset(progRtp, 0, sizeof(NET_PROGRESS_T));
  }
  if(progRtcp) {
    memset(progRtcp, 0, sizeof(NET_PROGRESS_T));
  }

  pRtpMulti = pStream->pRtpMulti;
  while(pRtpMulti) {

    if(g_proc_exit) {
      return -1;
    } else if(*pStream->prunning != STREAMER_STATE_RUNNING) {
      continue; 
    }

    //
    // Check if the RTP socket is pending creation by the capture_socket  thread
    //
    if(progRtp && pRtpMulti->pStreamerCfg->sharedCtxt.state == STREAMER_SHARED_STATE_PENDING_CREATE) {
      progRtp->numTotal++;
      continue;
    }

    for(idxDest = 0; idxDest < pRtpMulti->numDests; idxDest++) {

      if(!(pDest = &pRtpMulti->pdests[idxDest]) || !pDest->isactive) {
        continue;
      }

      sameRtpSock = sameRtcpSock = 0;

      if(pRtpMultiPrior) {
        //
        // Check RTP video/audio multiplexing over the same port
        //
        for(idxDestPrior = 0; idxDestPrior < pRtpMultiPrior->numDests; idxDestPrior++) {

          if(!(pDestPrior = &pRtpMultiPrior->pdests[idxDestPrior]) || !pDestPrior->isactive) {
            continue;
          }

          if(pDestPrior->saDsts.sin_port == pDest->saDsts.sin_port) {
            sameRtpSock = 1;
          }
          if(pDestPrior->saDstsRtcp.sin_port == pDest->saDstsRtcp.sin_port) {
            sameRtcpSock = 1;
          }
        }
      }


      //if(pDest->pRtpMulti->pStreamerCfg->xcode.vid.pip.active) 
      //LOG(X_DEBUG("SAMERTPSOCK:%D, SAMERTCPSOCK:%d"), sameRtpSock, sameRtcpSock);

      if(progRtp && (STREAM_RTP_PNETIOSOCK(*pDest)->flags & NETIO_FLAG_SSL_DTLS) && !sameRtpSock &&
         STREAM_RTP_FD(*pDest) != INVALID_SOCKET) {
        //if(pDest->pRtpMulti->pStreamerCfg->xcode.vid.pip.active) 
        //LOG(X_DEBUG("DO_DTLS_HS RTP pnetsock.state: %d, flags:0x%x"), STREAM_RTP_PNETIOSOCK(*pDest)->ssl.state, STREAM_RTP_PNETIOSOCK(*pDest)->flags);

        do_dtls_handshake(STREAM_RTP_PNETIOSOCK(*pDest), &pDest->saDsts, progRtp);
      }

      if(progRtcp && STREAM_RTP_FD(*pDest) != STREAM_RTCP_FD(*pDest) &&
        (STREAM_RTCP_PNETIOSOCK(*pDest)->flags & NETIO_FLAG_SSL_DTLS) && !sameRtcpSock &&
         STREAM_RTCP_FD(*pDest) != INVALID_SOCKET) {
        //if(pDest->pRtpMulti->pStreamerCfg->xcode.vid.pip.active) 
        //LOG(X_DEBUG("DO_DTLS_HS RCTP pnetsock.state: %d, flags:0x%x"), STREAM_RTCP_PNETIOSOCK(*pDest)->ssl.state, STREAM_RTCP_PNETIOSOCK(*pDest)->flags);

        do_dtls_handshake(STREAM_RTCP_PNETIOSOCK(*pDest), &pDest->saDstsRtcp, progRtcp);
      }

    } // end of for(idxDest..

    pRtpMultiPrior = pRtpMulti;
    pRtpMulti = pRtpMulti->pnext;
  } // end of while(pRtpMulti...

  //LOG(X_DEBUG("streamer_do_dtls_handshake done rtp-numDtls:%d, rtp-numDtlsCompleted:%d, rtcp-numDtls:%d, rtcp-numDtlsCompleted:%d"), progRtp ? progRtp->numTotal : -1, progRtp ? progRtp->numCompleted : -1, progRtcp->numTotal, progRtcp->numCompleted);

  if(!progRtp) {
    return 0;
  } if(progRtp->numError > 0) {
    return -1;
  } else if(progRtp->numCompleted == progRtp->numTotal) {

    if(*ptmstartRtpHandshakeDone == 0) {
      *ptmstartRtpHandshakeDone = timer_GetTime();
    }

    if(progRtcp->numTotal - progRtcp->numCompleted > 0 &&
      ((tmnow = timer_GetTime()) - *ptmstartRtpHandshakeDone) / TIME_VAL_MS < pdtlsTimeouts->handshakeRtcpAdditionalMs) {
      return progRtcp->numTotal - progRtcp->numCompleted;
    } else {
      return 0;
    }

  } else {

    if(((tmnow = timer_GetTime()) - tmstart) / TIME_VAL_MS > pdtlsTimeouts->handshakeRtpTimeoutMs) {
      LOG(X_ERROR("Aborting DTLS RTP handshake(s) after %lld ms.  %d/%d completed"), 
          (tmnow - tmstart) / TIME_VAL_MS, progRtp->numCompleted, progRtp->numTotal);
      return -1;
    } else {
      return progRtp->numTotal - progRtp->numCompleted;
    }

  }

}
Exemplo n.º 16
0
static void stream_monitor_proc(void *pArg) {
    MONITOR_START_WRAP_T startWrap;
    STREAM_STATS_MONITOR_T *pMonitor = NULL;
    FILE *fp = NULL;
    unsigned int intervalMs;
    TIME_VAL tvNext, tv;

    memcpy(&startWrap, pArg, sizeof(startWrap));
    pMonitor = startWrap.pMonitor;

    logutil_tid_add(pthread_self(), startWrap.tid_tag);

    pMonitor->runMonitor = 1;
    if((intervalMs = pMonitor->dumpIntervalMs) <= 0) {
        intervalMs = STREAM_STATS_DUMP_MS;
    }

    //
    // Set the output file path
    //
    if(pMonitor->statfilepath) {
        if(!strcasecmp(pMonitor->statfilepath, "stdout")) {
            fp = stdout;
        } else if(!strcasecmp(pMonitor->statfilepath, "stderr")) {
            fp = stderr;
        } else if(!(fp = fopen(pMonitor->statfilepath, "w"))) {
            LOG(X_ERROR("Failed top open stats file %s for writing"), pMonitor->statfilepath);
            pMonitor->runMonitor = -1;
        }
    } else {
        //fp = stdout;
    }

    if(pMonitor->runMonitor == 1) {
        tvNext = timer_GetTime() + (intervalMs * TIME_VAL_MS);
        LOG(X_INFO("Started %sstream output monitor %s%s"),
            pMonitor->pAbr ? "ABR " : "",
            pMonitor->statfilepath ? "to " : "",
            pMonitor->statfilepath ? pMonitor->statfilepath : "");
    }

    while(pMonitor->runMonitor == 1 && !g_proc_exit) {

        if((tv = timer_GetTime()) >= tvNext) {

            stream_monitor_dump(fp, pMonitor);

            tvNext += (intervalMs * TIME_VAL_MS);
        }

        usleep(100000);

    }

    if(fp) {
        fclose(fp);
    }

    pMonitor->runMonitor = -1;
    pthread_mutex_destroy(&pMonitor->mtx);
    pMonitor->active = -1;

    logutil_tid_remove(pthread_self());

}