static STREAM_STATS_T *stream_stats_create(const struct sockaddr_in *psaRemote, unsigned int numWr, unsigned int numRd, int rangeMs1, int rangeMs2) { STREAM_STATS_T *pStats = NULL; unsigned int idx; unsigned int periodMs; int rangeMs; int rc = 0; if(!(pStats = (STREAM_STATS_T *) avc_calloc(1, sizeof(STREAM_STATS_T)))) { return NULL; } pStats->active = 1; for(idx = 0; idx < THROUGHPUT_STATS_BURSTRATES_MAX; idx++) { rangeMs = idx == 0 ? rangeMs1 : rangeMs2; if(rangeMs <= 0) { continue; } periodMs = rangeMs / 10; rangeMs = periodMs * 10; if(rc >= 0 && numWr > 0) { // This is used for UDP / RTP output or general TCP based flow queue writing rc = burstmeter_init(&pStats->throughput_rt[0].bitratesWr[idx], periodMs, rangeMs); } if(rc >= 0 && numWr > 1) { // This is used for UDP / RTCP output rc = burstmeter_init(&pStats->throughput_rt[1].bitratesWr[idx], periodMs, rangeMs); } if(rc >= 0 && numRd > 0) { // This is used for general TCP based flow queue reading rc = burstmeter_init(&pStats->throughput_rt[0].bitratesRd[idx], periodMs, rangeMs); } if(rc < 0) { stream_stats_destroy(&pStats, NULL); return NULL; } } if(psaRemote) { memcpy(&pStats->saRemote, psaRemote, sizeof(pStats->saRemote)); } pStats->numWr = numWr; pStats->numRd = numRd; pthread_mutex_init(&pStats->mtx, NULL); return pStats; }
int streamxmit_init(STREAM_RTP_DEST_T *pDest, const STREAM_DEST_CFG_T *pDestCfg) { unsigned int numPkts = 0; unsigned int szPkt; int iTmp; STREAM_XMIT_QUEUE_T *pAsyncQ = NULL; PKTQUEUE_T *pQ = NULL; STREAM_STATS_MONITOR_T *pMonitor = NULL; if(!pDest || !pDestCfg) { return -1; } pAsyncQ = &pDest->asyncQ; if(pDestCfg->pFbReq && pDestCfg->pFbReq->nackRtpRetransmit) { pAsyncQ->doRtcpNack = 1; } pAsyncQ->doAsyncXmit = 0; // TODO: implement for packet output smoothing // // We run if we are to do async RTP xmit // or we support RTP-retransmissions for video (using RTCP NACK notifications) // if(!pAsyncQ->doAsyncXmit && (!pAsyncQ->doRtcpNack || pDest->pRtpMulti->isaud)) { return 0; } if(pAsyncQ->doRtcpNack) { // // Compute an RTP retransmission queue size // if(pDest->pRtpMulti->pStreamerCfg->xcode.vid.common.cfgDo_xcode && pDest->pRtpMulti->pStreamerCfg->xcode.vid.out[pDestCfg->xcodeOutidx].cfgBitRateOut > 0 && pDest->pRtpMulti->init.maxPayloadSz > 0) { iTmp = (pDest->pRtpMulti->pStreamerCfg->xcode.vid.out[pDestCfg->xcodeOutidx].cfgBitRateOut / (8 * 10 * pDest->pRtpMulti->init.maxPayloadSz) + 2) * 10; numPkts = MIN(150, MAX(50, iTmp)); } else { numPkts = 100; } //TODO: really only need burstmeter when capping retransmission traffic burstmeter_init(&pAsyncQ->retransmissionMeter, 1, 1000); //pAsyncQ->retransmissionKbpsMax = 30; } else { numPkts = 40; } szPkt = pDest->pRtpMulti->init.maxPayloadSz + RTP_HEADER_LEN + DTLS_OVERHEAD_SIZE + 64; // No locking!... should rely on pAsyncQ->mtx if(!(pQ = pktqueue_create(numPkts, szPkt, 0, 0, 0, sizeof(STREAMXMIT_PKT_HDR_T), 0, 1))) { return -1; } LOG(X_DEBUG("Created RTP %soutput packet queue size: %dB x %dpkts"), pAsyncQ->doRtcpNack ? "NACK " : "", szPkt, numPkts); pQ->cfg.overwriteType = PKTQ_OVERWRITE_OK; pQ->cfg.id = STREAMER_QID_NACK; pktqueue_setrdr(pQ, 0); pthread_mutex_init(&pAsyncQ->mtx, NULL); pAsyncQ->nackHistoryMs = RTP_RETRANSMIT_HISTORY_MS; pAsyncQ->pQ = pQ; // // Start the RTP output queue processor thread // if(pDestCfg->pMonitor && pDestCfg->pMonitor->active) { pMonitor = pDestCfg->pMonitor; } streamxmit_async_start(pDest->pRtpMulti, pMonitor, 0); return 0; }