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; }
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; }
//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; }
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 }
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; }
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; }