Пример #1
0
static int waitForFileContent(MP4_FILE_STREAM_T *pMp4Fs, unsigned int len) {
  //int rc = 0;
  struct stat st;
  FILE_STREAM_T *pFs = (FILE_STREAM_T *) pMp4Fs->pCbData;
  CAP_ASYNC_DESCR_T *pCapCfg = (CAP_ASYNC_DESCR_T *) pMp4Fs->pUserData;
  CAP_HTTP_MP4_T *pCapHttpMp4 = (CAP_HTTP_MP4_T *) pCapCfg->pUserData;
  struct timeval tv0, tv;
  unsigned int rcvTmtMs = pCapHttpMp4->mp4NetStream.rcvTmtMs;

  //fprintf(stderr, "WAIT FOR FILE C PUSERDATA: 0x%x\n", pCapCfg->pUserData);

  gettimeofday(&tv0, NULL);

  while(pFs->offset + len > pFs->size) {

    if(pCapCfg->running != 0 || g_proc_exit) {
      return -1;
    }

    //
    // Check the current file size to see if we have enough content to read
    //
    if(fileops_stat(pFs->filename, &st) != 0) {
      LOG(X_ERROR("Unable to get file size of '%s'."), pFs->filename);
      return -1;
    } else if(st.st_size != pFs->size) {
      pFs->size = st.st_size;
      pMp4Fs->size = pFs->size;
    }

    //
    // If the file does not have enough content to read, sleep and try again
    //
    if(pFs->offset + len > pFs->size) {

      //fprintf(stderr, "waitForFileContent... '%s', offset:%llu, len:%u, size:%llu, sleeping...\n", pFs->filename, pFs->offset, len, pFs->size);

      gettimeofday(&tv, NULL);
      if(TIME_TV_DIFF_MS(tv, tv0) > rcvTmtMs) {
        LOG(X_WARNING("Timeout %u ms exceeded when waiting for frame in '%s'"), 
                      rcvTmtMs, pMp4Fs->cbGetName(pMp4Fs));
        pCapHttpMp4->rcvState.error = MP4_RCV_ERROR_RD_TMT;
        return -1;
      }

      usleep(10000);
    }

  }

  if(pCapCfg->running != 0 || g_proc_exit) {
    return -1;
  }

  return 0;
}
Пример #2
0
static const char *get_m3u8(CAP_ASYNC_DESCR_T *pCfg,
                         const char *puri,
                         HTTP_RESP_T *pHttpResp,
                         HTTP_PARSE_CTXT_T *pHdrCtxt,
                         unsigned char *pbuf, unsigned int szbuf) {
  int sz = 0;
  struct timeval tv0, tv1;
  unsigned int consumed = 0;
  unsigned int contentLen = 0;
  unsigned int tmtms = 0;
  unsigned char *pdata = NULL;

  gettimeofday(&tv0, NULL);

  //fprintf(stderr, "GET M3U... puri:'%s', hdrslen:%d\n", puri, pHdrCtxt->hdrslen);

  if(pHdrCtxt->hdrslen == 0) {

    if((httpcli_gethdrs(pHdrCtxt, pHttpResp, &pCfg->pSockList->salist[0], puri,
          http_getConnTypeStr(HTTP_CONN_TYPE_CLOSE), 0, 0, pCfg->pcommon->addrsExtHost[0], NULL)) < 0) {
      return NULL;
    }

  }

  if((pdata = http_get_contentlen_start(pHttpResp, pHdrCtxt, pbuf, szbuf, 1, &contentLen))) {
    consumed = pHdrCtxt->idxbuf - pHdrCtxt->hdrslen;
  }

  if(pdata && net_setsocknonblock(NETIOSOCK_FD(pCfg->pSockList->netsockets[0]), 1) < 0) {
 
    pdata = NULL;
  }

//fprintf(stderr, "NET_RECV in m3u... %d < %d idxbuf:%d hdrslen:%d pdata:0x%x\n", consumed, contentLen, pHdrCtxt->idxbuf, pHdrCtxt->hdrslen, pdata);

  while(pdata && consumed < contentLen && !g_proc_exit) {

    if((sz = netio_recvnb(&pCfg->pSockList->netsockets[0],
                          (unsigned char *) &pdata[consumed],
                          contentLen - consumed, 500)) > 0) {
      consumed += sz;
    }
//fprintf(stderr, "NET REceiving... %d < %d, %d tmtms:%d\n", consumed, contentLen, sz, tmtms);
    gettimeofday(&tv1, NULL);
    if(tmtms > 0 && consumed < contentLen && TIME_TV_DIFF_MS(tv1, tv0) > (unsigned int) tmtms) {
      LOG(X_WARNING("HTTP %s:%d%s timeout %d ms exceeded"),
           inet_ntoa(pCfg->pSockList->salist[0].sin_addr),
           ntohs(pCfg->pSockList->salist[0].sin_port), puri, tmtms);
      pdata = NULL;
      break;
    }
  }

  if(pdata && contentLen > 0 && consumed >= contentLen) {
    pdata[consumed] = '\0';
  } else {
    pdata = NULL;
  }

  //fprintf(stderr, "GOT m3u...0x%x %d < %d\n", pdata, consumed, contentLen);avc_dumpHex(stderr, pdata, consumed, 1);
  return (const char *) pdata;
}
Пример #3
0
//TODO: move this to http files
int http_getpage(const char *addr, uint16_t port, const char *uri,
                 char *buf, unsigned int szbuf, unsigned int tmtms) {
  int rc = 0;
  NETIO_SOCK_T netsock;
  struct sockaddr_in sa;
  HTTP_PARSE_CTXT_T hdrCtxt;
  HTTP_RESP_T httpResp;
  unsigned int contentLen = 0;
  const char *p;
  unsigned int consumed = 0;
  struct timeval tv0, tv1;
  char hdr[1024];

  if(!addr || !buf || szbuf <= 0) {
    return -1;
  }
  if(!uri) {
    uri = "/";
  }

  memset(&netsock, 0, sizeof(netsock));
  if((NETIOSOCK_FD(netsock) = net_opensocket(SOCK_STREAM, 0, 0, NULL)) == INVALID_SOCKET) {
    return -1;
  }

  memset(&sa, 0, sizeof(sa));
  sa.sin_addr.s_addr = inet_addr(addr);
  sa.sin_port = htons(port);

  if((rc = net_connect(NETIOSOCK_FD(netsock), &sa)) != 0) {
    return rc;
  }

  gettimeofday(&tv0, NULL);

  memset(&hdrCtxt, 0, sizeof(hdrCtxt));
  memset(&httpResp, 0, sizeof(httpResp));
  hdrCtxt.pnetsock = &netsock;
  hdrCtxt.pbuf = hdr;
  hdrCtxt.szbuf = sizeof(hdr);
  hdrCtxt.tmtms = tmtms;

  VSX_DEBUG_MGR(LOG(X_DEBUG("MGR - Sending local status command: '%s' to: %d"), uri, htons(sa.sin_port)));

  if((httpcli_gethdrs(&hdrCtxt, &httpResp, &sa, uri, NULL, 0, 0, NULL, NULL)) < 0) {
    return -1;
  }

  if(rc >= 0 && (p = conf_find_keyval(httpResp.hdrPairs, HTTP_HDR_CONTENT_LEN))) {
    contentLen = atoi(p);  
  } 

  if(rc >= 0) {
    if(contentLen <= 0) {
      LOG(X_ERROR("Content-Length not found in response"));
      rc = -1;
    } else if(contentLen > szbuf) {
      LOG(X_ERROR("Input buffer size too small %d / %d"), szbuf, contentLen);
      rc = -1;
    } else if(hdrCtxt.idxbuf > hdrCtxt.hdrslen) {
      if((consumed = hdrCtxt.idxbuf - hdrCtxt.hdrslen) < szbuf) {
        memcpy(buf, &hdr[hdrCtxt.hdrslen], consumed);
      } else {
        LOG(X_ERROR("Input buffer size too small %d / %d"), szbuf, contentLen);
        rc = -1;
      }
    }
  }

  if(rc >= 0 && net_setsocknonblock(NETIOSOCK_FD(netsock), 1) < 0) {
    rc = -1;
  } 

    //fprintf(stderr, "GET PAGE OK idx:%d hdrs:%d conentlen:%d\n", hdrCtxt.idxbuf, hdrCtxt.hdrslen, contentLen);

  while(rc >= 0 && consumed < contentLen) {
    if((rc = netio_recvnb(&netsock, (unsigned char *) &buf[consumed], 
                          contentLen - consumed, 500)) > 0) {
      consumed += rc;
    } 

    gettimeofday(&tv1, NULL);
    if(tmtms > 0 && consumed < contentLen && TIME_TV_DIFF_MS(tv1, tv0) > tmtms) {
      LOG(X_WARNING("HTTP %s:%d%s timeout %d ms exceeded"), net_inet_ntoa(sa.sin_addr, hdr), 
           ntohs(sa.sin_port), uri, tmtms);
      break;
      rc = -1;
    }
  }

  if(contentLen > 0 && consumed >= contentLen) {
    rc = consumed;
  } else {
    rc = -1;
  }

  netio_closesocket(&netsock);

  return rc;
}
Пример #4
0
static void procdb_monitor_proc(void *pArg) {
  SYS_PROCLIST_T *pProcs = (SYS_PROCLIST_T *) pArg;
  SYS_PROC_T *pProc, *pProcTmp;
  SYS_PROC_T *pProcPrev;
  int remove;
  int rc;
  char logstr[128];
  struct timeval *ptvlatest;
  struct timeval tvnow;

  while(pProcs->runMonitor) {

    //procdb_dump(pProcs);

    gettimeofday(&tvnow, NULL);
    pProcPrev = NULL;
    pProc = pProcs->procs;

    while(pProc) {

      remove = 0;
      if((pProc->flags & SYS_PROC_FLAG_RUNNING)) {

        if((rc = procutil_isrunning(pProc->pid)) < 0) {
          remove = 1;
          snprintf(logstr, sizeof(logstr), "Unable to determine process state");
        } else if(rc == 0) {
          remove = 1;
          snprintf(logstr, sizeof(logstr), "Process has ended");
        } else {

          //
          // Poll the child process to see how many active sessions are being serviced
          //
          if(TIME_TV_DIFF_MS(tvnow, pProc->tmLastPoll) > pProcs->pollIntervalMs) {
//fprintf(stderr, "checkign status\n");
            check_status(pProc);
//fprintf(stderr, "checkign status done numActive:%d\n", pProc->numActive);
            memcpy(&pProc->tmLastPoll, &tvnow, sizeof(pProc->tmLastPoll));
            if(pProc->numActive > 0) {
              memcpy(&pProc->tmLastPollActive, &tvnow, sizeof(pProc->tmLastPollActive));
            }
          }

          if(pProc->tmLastAccess.tv_sec > pProc->tmLastPollActive.tv_sec) {
//fprintf(stderr, "last access is higher\n");
            ptvlatest = &pProc->tmLastAccess; 
          } else {
//fprintf(stderr, "last poll is higher\n");
            ptvlatest = &pProc->tmLastPollActive; 
          }
          
//fprintf(stderr, "comparing %d\n", tvnow.tv_sec - ptvlatest->tv_sec);
          if(tvnow.tv_sec > ptvlatest->tv_sec + pProcs->procexpiresec) {
            snprintf(logstr, sizeof(logstr), "Expiring idle process");
            remove = 1;
          }
        }

      }
        
      if(remove) {

        LOG(X_DEBUG("%s '%s' instance id: %s, id:'%s', pid:%d, flags:0x%x (active: %d/%d, xcode: %d/%d)"), 
            logstr, pProc->name, pProc->instanceId, pProc->id, pProc->pid, pProc->flags, 
          pProcs->activeInstances, pProcs->maxInstances, pProcs->activeXcodeInstances, 
          pProcs->maxXcodeInstances);

        if(procutil_kill_block(pProc->pid) < 0) {
          LOG(X_ERROR("Unable to kill process '%s' instance id: %s, pid:%d"), 
              pProc->name, pProc->instanceId, pProc->pid);
        }

        pthread_mutex_lock(&pProcs->mtx); 
        if(pProcPrev) {
          pProcPrev->pnext = pProc->pnext;
        }
        if(pProcs->procs == pProc) {
          pProcs->procs = pProc->pnext;
        }

        if(pProcs->activeInstances > 0) {
          pProcs->activeInstances--;
        }
        if(pProc->isXcoded && pProcs->activeXcodeInstances > 0) {
          pProcs->activeXcodeInstances--;
        }
        if(pProc->mbbps > 0 && pProcs->mbbpsTot > pProc->mbbps) {
          pProcs->mbbpsTot -= pProc->mbbps;
        }

        pProcTmp = pProc->pnext;
        free(pProc);
        pProc = pProcTmp;
        pthread_mutex_unlock(&pProcs->mtx); 

      } else { 
        pProcPrev = pProc;
        pProc = pProc->pnext;
      }

    }  // end of while(pProc

    usleep(1000000);

  } // end of while(runMonitor

}
Пример #5
0
static int stream_stats_dump(char *buf, unsigned int szbuf, STREAM_STATS_T *pStats, int urlidx) {
    int rc;
    uint32_t durationms;
    float fracLost, f;
    unsigned int idxbuf = 0;
    STREAM_RTP_INIT_T *pRtpInit;
    char buftmp[2048];

    if(pStats->tvstart.tv_sec > 0) {
        durationms = TIME_TV_DIFF_MS(pStats->tv_last, pStats->tvstart);
    } else {
        durationms = 0;
    }

    printDuration(buftmp, sizeof(buftmp), durationms);

    if((urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, "&method%d=%s&duration%d=%s&host%d=%s:%d",
                                 urlidx, devtype_methodstr(pStats->method), urlidx, buftmp, urlidx,
                                 inet_ntoa(pStats->saRemote.sin_addr), htons(pStats->saRemote.sin_port))) > 0) ||
            (!urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, "%7s %s -> %15s:%d",
                                       devtype_methodstr(pStats->method), buftmp,
                                       inet_ntoa(pStats->saRemote.sin_addr), htons(pStats->saRemote.sin_port))) > 0)) {
        idxbuf += rc;
    }

    if(pStats->pRtpDest && pStats->pRtpDest->pRtpMulti) {
        pRtpInit = &pStats->pRtpDest->pRtpMulti->init;
        if((urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, "&pt%d=%d", urlidx, pRtpInit->pt)) > 0) ||
                (!urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, " pt:%3d", pRtpInit->pt)) > 0)) {
            idxbuf += rc;
        }
    }

    if((rc = snprintf(&buf[idxbuf], szbuf - idxbuf,
                      "%s", dump_throughput(buftmp, sizeof(buftmp), "", &pStats->throughput_last[0], urlidx))) > 0) {
        idxbuf += rc;
    }

    if(pStats->numWr > 1 && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf,
                                           "%s", dump_throughput(buftmp, sizeof(buftmp), "rtcp ", &pStats->throughput_last[1], urlidx))) > 0) {
        idxbuf += rc;
    }

    if(pStats->ctr_last.ctr_rrRcvd > 0) {
        //fprintf(fp, " ctr_last.ctr_rrRcvd:%d", pStats->ctr_last.ctr_rrRcvd);
        if(pStats->ctr_last.ctr_rrdelaySamples > 0) {
            f = (float) pStats->ctr_last.ctr_rrdelayMsTot / pStats->ctr_last.ctr_rrdelaySamples;

            if((urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, "&rtdelay%d=%.1f", urlidx, f)) > 0) ||
                    (!urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, ", rtdelay: %.1f", f)) > 0)) {
                idxbuf += rc;
            }
        }

        if(pStats->ctr_last.ctr_fracLostSamples > 0) {
            fracLost = pStats->ctr_last.ctr_fracLostTot / pStats->ctr_last.ctr_fracLostSamples;

            if((urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, "&fraclost%d=%.2f", urlidx, fracLost)) > 0) ||
                    (!urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, ", frac-lost: %.2f%%", fracLost)) > 0)) {
                idxbuf += rc;
            }
        }

        if(pStats->ctr_last.cumulativeSeqNum > 0) {
            fracLost = (float) 100.0f * pStats->ctr_last.cumulativeLostPrev / pStats->ctr_last.cumulativeSeqNum;
        } else {
            fracLost = 0;
        }

        if((urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, "&cml-lost%d=%d&cml-pkts%d=%u&tot-lost%d=%u&tot%d=%u&fractotlost%d=%.2f",
                                     urlidx, pStats->ctr_last.ctr_cumulativeLost,
                                     urlidx, pStats->ctr_last.ctr_countseqRr,
                                     urlidx, pStats->ctr_last.cumulativeLostPrev,
                                     urlidx, pStats->ctr_last.cumulativeSeqNum,
                                     urlidx, fracLost)) > 0) ||

                (!urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf,
                                           ", cml-lost: %d/%d (all:%d/%d, %.2f%%)", pStats->ctr_last.ctr_cumulativeLost,
                                           pStats->ctr_last.ctr_countseqRr, pStats->ctr_last.cumulativeLostPrev, pStats->ctr_last.cumulativeSeqNum, fracLost)) > 0)) {

            idxbuf += rc;
        }
    }

    if(!urlidx && (rc = snprintf(&buf[idxbuf], szbuf - idxbuf, "\n")) > 0) {
        idxbuf += rc;
    }

    return (int) idxbuf;
}
Пример #6
0
int httplive_cbOnPkt(void *pUserData, const unsigned char *pPktData, unsigned int len) {
  int rc = 0, rc2;
  struct timeval tv;
  char filename[VSX_MAX_PATH_LEN];
  unsigned int idxMin = 0;
  int keepIdx;
  HTTPLIVE_DATA_T *pLive = (HTTPLIVE_DATA_T *) pUserData;

  if(!pLive || !pPktData) {
    return -1;
  }

  //fprintf(stderr, "httplive_cbOnPkt len:%d, outidx[%d]\n", len, pLive->outidx);

  if(len == 0) {
    LOG(X_WARNING("httplive cb called with 0 length"));
    return 0;  
  }

  gettimeofday(&tv, NULL);

  if(pLive->tvNextRoll.tv_sec == 0 ||
     TIME_TV_DIFF_MS(tv, pLive->tvNextRoll) >= (long) (pLive->duration * 1000.0f)) {

    if(pLive->fs.fp != FILEOPS_INVALID_FP) {
      //LOG(X_DEBUG("HTTPLIVE CLOSING fp:0x%x, fileno:%d %s"), pLive->fs.fp, pLive->fs.fp ? fileno(pLive->fs.fp) : -99, pLive->fs.filename);
      closeFp(pLive);
      //LOG(X_DEBUG("HTTPLIVE CLOSED fp:0x%x, fileno:%d %s"), pLive->fs.fp, pLive->fs.fp ? fileno(pLive->fs.fp) : -99, pLive->fs.filename);
    }

    keepIdx = HTTPLIVE_NUM_INDEXES_KEEP(pLive);

    if(pLive->curIdx > keepIdx + 2) {
      idxMin = pLive->curIdx - keepIdx - 2;
      httplive_purgetsfiles(pLive, idxMin);
    }

    //
    // Update MPEG-DASH playlist using .ts segments
    //
    if(pLive->pMpdMp2tsCtxt && pLive->curIdx > 0) {
      on_new_ts(pLive->curIdx-1, idxMin, pLive->outidx, 
                pLive->dir, pLive->curIdx,
               //pLive->fs.filename, 
                pLive->pMpdMp2tsCtxt, 90000, (pLive->duration * 90000), 
                TIME_TV_DIFF_MS(pLive->tvPriorRoll, pLive->tvRoll0) * 90);
    }

    httplive_format_path(filename, sizeof(filename), pLive->fileprefix, pLive->curIdx);
    mediadb_prepend_dir(pLive->dir, filename, pLive->fs.filename, sizeof(pLive->fs.filename));

    if((pLive->fs.fp = fileops_Open(pLive->fs.filename, O_RDWR | O_CREAT)) == FILEOPS_INVALID_FP) {
      LOG(X_ERROR("Failed to open '%s' for writing"), pLive->fs.filename);
      rc = -1;    
    } else {

      LOG(X_DEBUG("Opened '%s'"), pLive->fs.filename);

      rc = httplive_updatepl(pLive);

    }

    pLive->curIdx++;
    if(pLive->tvNextRoll.tv_sec == 0) {
      TIME_TV_SET(pLive->tvNextRoll, tv);
      TIME_TV_SET(pLive->tvRoll0, tv);
    }
    //fprintf(stderr, "TV  at %u:%u\n", tv.tv_sec, tv.tv_usec);
    
    TIME_TV_SET(pLive->tvPriorRoll, pLive->tvNextRoll);
    TV_INCREMENT_MS(pLive->tvNextRoll, (pLive->duration * 1000.0f));
    //fprintf(stderr, "TV next at %u:%u, msElapsed:%u, idxMin:%d, curIdx:%d\n", pLive->tvNextRoll.tv_sec, pLive->tvNextRoll.tv_usec, TIME_TV_DIFF_MS(pLive->tvNextRoll, pLive->tvRoll0), idxMin, pLive->curIdx);

  }

  //LOG(X_DEBUG("HTTPLIVE WRITE  %d fp:0x%x, pPktData:0x%x, fileno:%d %s"), len, pLive->fs.fp, pPktData, pLive->fs.fp ? fileno(pLive->fs.fp) : -99, pLive->fs.filename);
  if(pLive->fs.fp != FILEOPS_INVALID_FP &&
     (rc2 = fileops_WriteBinary(pLive->fs.fp, (unsigned char *) pPktData, len)) != len) {
    LOG(X_ERROR("Failed to write %d/%d to output ts %s"), rc2, len, pLive->fs.filename);

    //LOG(X_DEBUG("HTTPLIVE WRITE ERROR %d, %d fp:0x%x, pPktData:0x%x, fileno:%d %s"), rc2, len, pLive->fs.fp, pPktData, pLive->fs.fp ? fileno(pLive->fs.fp) : -99, pLive->fs.filename);
    return -1;
  }


  return rc;
}