static int sendRtcpSr(STREAM_XMIT_NODE_T *pStream, unsigned int idxDest) { int rc = 0; unsigned char buf[256]; int len = 0; if(!pStream->pXmitAction->do_output_rtphdr) { return 0; } if((len = stream_rtcp_createsr(pStream->pRtpMulti, idxDest, buf, sizeof(buf))) < 0) { LOG(X_ERROR("Unable to create rtcp sr for destination[%d]"), idxDest); return -1; } //fprintf(stderr, "sendto rtcp sr [dest:%d] %s:%d %d pkt:%u,%u ts:%u\n", idxDest, inet_ntoa(pStream->saDstsRtcp[idxDest].sin_addr), ntohs(pStream->saDstsRtcp[idxDest].sin_port), len, pStream->pRtpMulti[idxDest].rtcp.sr.pktcnt,pStream->pRtpMulti[idxDest].rtcp.sr.octetcnt,htonl(pStream->pRtpMulti[idxDest].rtcp.sr.rtpts)); if((rc = sendto(STREAM_RTCP_FD(pStream->pRtpMulti->pdests[idxDest]), (void *) buf, len, 0, (struct sockaddr *) &pStream->pRtpMulti->pdests[idxDest].saDstsRtcp, sizeof(pStream->pRtpMulti->pdests[idxDest].saDstsRtcp))) != len) { LOG(X_ERROR("sendto (rtcp) %s:%d for %d bytes failed with "ERRNO_FMT_STR), inet_ntoa(pStream->pRtpMulti->pdests[idxDest].saDstsRtcp.sin_addr), ntohs(pStream->pRtpMulti->pdests[idxDest].saDstsRtcp.sin_port), len, ERRNO_FMT_ARGS); return -1; } return rc; }
static int httplive_delete(HTTPLIVE_DATA_T *pLive) { char path[VSX_MAX_PATH_LEN]; char buf[VSX_MAX_PATH_LEN]; struct stat st; httplive_purgetsfiles(pLive, 0xffffffff); // // Delete the playlist // if(snprintf(buf, sizeof(buf), "%s"HTTPLIVE_PL_NAME_EXT, pLive->fileprefix) >= 0) { mediadb_prepend_dir(pLive->dir, buf, path, sizeof(path)); if(fileops_stat(path, &st) == 0 && fileops_DeleteFile(path) != 0) { LOG(X_ERROR("Failed to delete '%s'"), path); } } // // Delete any multi-bitrate playlist // if(snprintf(buf, sizeof(buf), "%s"HTTPLIVE_PL_NAME_EXT, HTTPLIVE_MULTIBITRATE_NAME_PRFX) >= 0) { mediadb_prepend_dir(pLive->dir, buf, path, sizeof(path)); if(fileops_stat(path, &st) == 0 && fileops_DeleteFile(path) != 0) { LOG(X_ERROR("Failed to delete '%s'"), path); } } return 0; }
int srvlisten_startrtsplive(SRV_LISTENER_CFG_T *pListenCfg) { pthread_t ptdRtspLive; pthread_attr_t attrRtspLive; const char *s; int rc = 0; if(!pListenCfg || !pListenCfg->pConnPool || pListenCfg->max <= 0 || !pListenCfg->pCfg || !pListenCfg->pCfg->cfgShared.pRtspSessions || pListenCfg->pCfg->cfgShared.pRtspSessions->max <= 0) { return -1; } if((pListenCfg->netflags & NETIO_FLAG_SSL_TLS) && !netio_ssl_enabled(1)) { LOG(X_ERROR("SSL not enabled")); return -1; } if((s = logutil_tid_lookup(pthread_self(), 0)) && s[0] != '\0') { snprintf(pListenCfg->tid_tag, sizeof(pListenCfg->tid_tag), "%s-rtsp", s); } pthread_attr_init(&attrRtspLive); pthread_attr_setdetachstate(&attrRtspLive, PTHREAD_CREATE_DETACHED); if(pthread_create(&ptdRtspLive, &attrRtspLive, (void *) srvlisten_rtsplive_proc, (void *) pListenCfg) != 0) { LOG(X_ERROR("Unable to create rtsp listener thread")); return -1; } return rc; }
int mp4_initMp4vTrack(const MP4_CONTAINER_T *pMp4, MP4_TRAK_MP4V_T *pMp4BoxSet) { if(!pMp4 || !pMp4BoxSet) { return -1; } if(!pMp4->pStream || !pMp4->pStream->cbCheckFd(pMp4->pStream)) { return -1; } memset(pMp4BoxSet, 0, sizeof(MP4_TRAK_MP4V_T)); if(pMp4->pStream->cbSeek(pMp4->pStream, 0, SEEK_SET) != 0) { return -1; } if((pMp4BoxSet->pMp4v = (BOX_MP4V_T *) mp4_loadTrack(pMp4->proot, &pMp4BoxSet->tk, *((uint32_t *) "mp4v"), 1)) == NULL) { LOG(X_ERROR("No valid mp4v track found in %s"), pMp4->pStream->cbGetName(pMp4->pStream)); return -1; } if((pMp4BoxSet->pEsds = (BOX_ESDS_T *) mp4_findBoxChild( (BOX_T *)pMp4BoxSet->pMp4v, *((uint32_t *) "esds"))) == NULL) { LOG(X_ERROR("No valid esds track found in %s"), pMp4->pStream->cbGetName(pMp4->pStream)); return -1; } return 0; }
void xcode_ipc_close(XCODE_IPC_DESCR_T *pXcodeIpc) { struct shmid_ds buf; memset(&buf, 0, sizeof(buf)); if(pXcodeIpc->shmid > 0) { if(pXcodeIpc->pmem) { shmdt(pXcodeIpc->pmem); pXcodeIpc->pmem = NULL; } shmctl(pXcodeIpc->shmid, IPC_RMID, &buf); pXcodeIpc->shmid = -1; } if(pXcodeIpc->sem_srv) { if(sem_close(pXcodeIpc->sem_srv) != 0) { LOG(X_ERROR("sem_close failed")); } pXcodeIpc->sem_srv = NULL; sem_unlink(XCODE_IPC_SEM_NAME_SRV); } if(pXcodeIpc->sem_cli) { if(sem_close(pXcodeIpc->sem_cli) != 0) { LOG(X_ERROR("sem_close failed")); } pXcodeIpc->sem_cli = NULL; sem_unlink(XCODE_IPC_SEM_NAME_CLI); } }
void xcode_ipc_close(XCODE_IPC_DESCR_T *pIpc) { if(pIpc) { if(pIpc->shmid > 0) { shmdt(pIpc->pmem); pIpc->shmid = 0; } if(pIpc->sem_srv) { if(sem_close(pIpc->sem_srv) != 0) { LOG(X_ERROR("sem_close srv failed")); } pIpc->sem_srv = NULL; } if(pIpc->sem_cli) { if(sem_close(pIpc->sem_cli) != 0) { LOG(X_ERROR("sem_close cli failed")); } pIpc->sem_cli = NULL; } free(pIpc); //fprintf(stderr, "close ipc ok\n"); } }
int mp4_initSamrTrack(const MP4_CONTAINER_T *pMp4, MP4_TRAK_SAMR_T *pMp4BoxSet) { if(!pMp4 || !pMp4BoxSet) { return -1; } if(!pMp4->pStream || !pMp4->pStream->cbCheckFd(pMp4->pStream)) { return -1; } memset(pMp4BoxSet, 0, sizeof(MP4_TRAK_SAMR_T)); if(pMp4->pStream->cbSeek(pMp4->pStream, 0, SEEK_SET) != 0) { return -1; } if((pMp4BoxSet->pSamr = (BOX_SAMR_T *) mp4_loadTrack(pMp4->proot, &pMp4BoxSet->tk, *((uint32_t *) "samr"), 1)) == NULL) { LOG(X_ERROR("No valid samr track found in %s"), pMp4->pStream->cbGetName(pMp4->pStream)); return -1; } if((pMp4BoxSet->pDamr = (BOX_DAMR_T *) mp4_findBoxChild( (BOX_T *)pMp4BoxSet->pSamr, *((uint32_t *) "damr"))) == NULL) { LOG(X_ERROR("No valid damr track found in %s"), pMp4->pStream->cbGetName(pMp4->pStream)); return -1; } return 0; }
static int parseIpPortStr(const char *localAddrStr, struct sockaddr_storage *pLocalAddr, uint16_t localPorts[], size_t maxLocalPorts, int requirePort) { size_t numPortsAdded = 0; int rc = 0; char host[512]; char ports[128]; char uri[512]; host[0] = '\0'; ports[0] = '\0'; uri[0] = '\0'; memset(localPorts, 0, sizeof(uint16_t) * maxLocalPorts); if((rc = strutil_parseAddress(localAddrStr, host, sizeof(host), ports, sizeof(ports), uri, sizeof(uri)) < 0)) { return rc; } if(net_getaddress(host, pLocalAddr) != 0 || (pLocalAddr->ss_family != AF_INET6 && ((struct sockaddr_in *) pLocalAddr)->sin_addr.s_addr == INADDR_NONE)) { LOG(X_ERROR("Invalid address specified in '%s'"), localAddrStr); return -1; } else if(!requirePort && ports[0] == '\0') { LOG(X_ERROR("No port specified in '%s'"), localAddrStr); return -1; } if((numPortsAdded = capture_parsePortStr(ports, localPorts, maxLocalPorts, 1)) < 0) { LOG(X_ERROR("Invalid port specified in '%s'"), localAddrStr); return numPortsAdded; } return numPortsAdded; }
static int dlts_netsock_onhandshake_completed(NETIO_SOCK_T *pnetsock) { int rc = 0; SRTP_PROTECTION_PROFILE *srtpProfile = NULL; unsigned char keys[DTLS_SRTP_KEYING_MATERIAL_SIZE]; if(!(pnetsock->flags & NETIO_FLAG_SRTP)) { return 0; } if(!(srtpProfile = SSL_get_selected_srtp_profile(pnetsock->ssl.pCtxt))) { LOG(X_ERROR("DTLS-SRTP SSL_get_selected_srtp_profile failed, peer may not be DTLS-SRTP capable: %s"), ERR_reason_error_string(ERR_get_error())); return -1; } memset(keys, 0, sizeof(keys)); if(SSL_export_keying_material(pnetsock->ssl.pCtxt, keys, sizeof(keys), DTLS_SRTP_KEYS_LABEL, strlen(DTLS_SRTP_KEYS_LABEL), NULL, 0, 0) != 1) { LOG(X_ERROR("DTLS-SRTP SSL_export_keying_material failed: %s"), ERR_reason_error_string(ERR_get_error())); return -1; } //LOG(X_DEBUG("dlts_netsock_onhandshake_completed DTLS-SRTP handshake selected profile: '%s', master-keys: "), srtpProfile->name); LOGHEX_DEBUG(keys, sizeof(keys)); if(pnetsock->ssl.dtlsKeysUpdateCtxt.cbKeyUpdateFunc) { pnetsock->ssl.dtlsKeysUpdateCtxt.cbKeyUpdateFunc(pnetsock->ssl.dtlsKeysUpdateCtxt.pCbData, pnetsock, srtpProfile->name, pnetsock->ssl.dtlsKeysUpdateCtxt.dtls_serverkey, pnetsock->ssl.dtlsKeysUpdateCtxt.is_rtcp, keys, sizeof(keys)); } return rc; }
static int getSampleDuration(BOX_STTS_T *pStts, unsigned int *pidxSampleInStts, unsigned int *pidxStts) { uint32_t sampleHz = 0; if(pStts->list.entrycnt == 0 || !pStts->list.pEntries) { LOG(X_ERROR("Invalid stts entry count: %u"), pStts->list.entrycnt); return -1; } else if(*pidxStts >= pStts->list.entrycnt) { LOG(X_ERROR("Invalid stts index referenced: %u/%u"), (*pidxStts)+1, pStts->list.entrycnt); return -1; } else if(*pidxSampleInStts >= pStts->list.pEntries[*pidxStts].samplecnt) { LOG(X_ERROR("Invalid stts[%u] entry index referenced: %u/%u"), *pidxStts, (*pidxSampleInStts)+1, pStts->list.pEntries[*pidxStts].samplecnt); return -1; } sampleHz = pStts->list.pEntries[*pidxStts].sampledelta; (*pidxSampleInStts)++; if(*pidxSampleInStts >= pStts->list.pEntries[*pidxStts].samplecnt) { *pidxSampleInStts = 0; (*pidxStts)++; } return (int) sampleHz; }
int capture_parseAuthUrl(const char **ppstr, AUTH_CREDENTIALS_STORE_T *pauth) { int rc = 0; const char *p; const char *pendcred = NULL; const char *pcolon = NULL; if(!ppstr || !(p = *ppstr)) { return -1; } // // Check if we have a username or pass // while(*p != '\0' && *p != '/' && *p != '@') { p++; } if(*p == '@') { pendcred = p; p = (*ppstr); // // Check if we have a username and pass // while(*p != '\0' && *p != ':' && *p != '@') { p++; } if(*p == ':') { pcolon = p; p++; if(pauth) { if(pendcred - p >= sizeof(pauth->pass)) { LOG(X_ERROR("Auth password credentials too long in: %s"), *ppstr); return -1; } memcpy(pauth->pass, p, (pendcred - p)); pauth->username[pendcred - p] = '\0'; } } else { pcolon = pendcred; } if(pauth) { if(pcolon - (*ppstr) >= sizeof(pauth->username)) { LOG(X_ERROR("Auth username credentials too long in: %s"), *ppstr); return -1; } memcpy(pauth->username, *ppstr, (pcolon - *ppstr)); pauth->username[pcolon - *ppstr] = '\0'; } } if(pendcred) { (*ppstr) += (pendcred - *ppstr + 1); } return rc; }
static int get_ts(HTTPLIVE_CLIENT_T *pClient, const char *puri) { int rc = 0; HTTP_PARSE_CTXT_T hdrCtxt; HTTP_RESP_T httpResp; const char *p = NULL; unsigned char *pdata; unsigned int contentLen = 0; char fulluri[256]; unsigned char buf[RTP_JTBUF_PKT_BUFSZ_LOCAL + SOCKET_LIST_PREBUF_SZ]; //LOG(X_DEBUG("Retrieving TS chunk '%s'"), puri); if(pClient->uriprefix[0] != '\0') { snprintf(fulluri, sizeof(fulluri), "%s%s", pClient->uriprefix, puri); puri = fulluri; } memset(&hdrCtxt, 0, sizeof(hdrCtxt)); memset(&httpResp, 0, sizeof(httpResp)); hdrCtxt.pnetsock = &pClient->netsock; hdrCtxt.pbuf = (char *) buf; hdrCtxt.szbuf = sizeof(buf); hdrCtxt.tmtms = 0; if((httpcli_gethdrs(&hdrCtxt, &httpResp, &pClient->sa, puri, http_getConnTypeStr(HTTP_CONN_TYPE_KEEPALIVE), 0, 0, pClient->hostbuf, NULL)) < 0) { return -1; } if(!(p = conf_find_keyval(httpResp.hdrPairs, HTTP_HDR_CONTENT_TYPE))) { LOG(X_ERROR("No "HTTP_HDR_CONTENT_TYPE" found in response")); return -1; } else if(!(strncasecmp(p, CONTENT_TYPE_MP2TS, strlen(CONTENT_TYPE_MP2TS)) && strncasecmp(p, CONTENT_TYPE_OCTET_STREAM, strlen(CONTENT_TYPE_OCTET_STREAM)))) { LOG(X_ERROR("Unsupported %s: %s received in response for %s"), HTTP_HDR_CONTENT_TYPE, (p ? p : "<Not Found>"), puri); rc = -1; } if(!(pdata = http_get_contentlen_start(&httpResp, &hdrCtxt, buf, sizeof(buf), 0, &contentLen))) { rc = -1; } //fprintf(stderr, "TS contentlen:%d pdata:0x%x idxb:%d hdrslen:%d\n", contentLen, pdata, hdrCtxt.idxbuf, hdrCtxt.hdrslen); if(rc >= 0 && pClient->pCfg->running == 0) { rc = http_recvloop(pClient->pCfg, &pClient->netsock, &pClient->sa, pClient->pStreamsOut, pClient->pStream, hdrCtxt.hdrslen, hdrCtxt.idxbuf - hdrCtxt.hdrslen, contentLen, buf, sizeof(buf)); } //fprintf(stderr, "TS DONE w rc:%d\n", rc); return rc; }
int mediadb_mkdirfull(const char *root, const char *path) { size_t idxprev; struct stat st; size_t sz = 0; size_t len; char buf[VSX_MAX_PATH_LEN]; // fprintf(stdout, "mkdirfull '%s' '%s'\n", root, path); if(!path) { return -1; } if(root) { sz = strlen(root); } buf[sizeof(buf) - 1] = '\0'; idxprev = sz; len = strlen(path); for(; sz < len && sz < sizeof(buf); sz++) { if(path[sz] == DIR_DELIMETER) { memset(buf, 0, sizeof(buf)); strncpy(buf, path, sz); //fprintf(stdout, "stat '%s'\n", buf); if(strlen(buf) > 0 && fileops_stat(buf, &st) != 0) { LOG(X_DEBUG("Creating dir '%s'"), buf); if(fileops_MkDir(buf, S_IRWXU | S_IRWXG | S_IRWXO ) < 0) { LOG(X_ERROR("Unable to create dir '%s'"), buf); return -1; } } while(path[sz] == DIR_DELIMETER) { sz++; } idxprev = sz; //fprintf(stdout, "after'%s'\n", &path[sz]); } } if(sz > idxprev && fileops_stat(path, &st) != 0) { LOG(X_DEBUG("Creating dir '%s'"), path); if(fileops_MkDir(path, S_IRWXU | S_IRWXG | S_IRWXO ) < 0) { LOG(X_ERROR("Unable to create dir '%s'"), path); return -1; } } return 0; }
int dtls_get_cert_fingerprint(const char *certPath, DTLS_FINGERPRINT_T *pFingerprint) { int rc = 0; unsigned int lenHash; X509 *pX509 = NULL; BIO *pBIO = NULL; const EVP_MD *pEvp = NULL; if(!certPath || !pFingerprint) { return -1; } pFingerprint->buf[0] = '\0'; pFingerprint->len = 0; if(!(pEvp = dtlsFingerprintTypeToEVP(pFingerprint->type))) { LOG(X_ERROR("DTLS invalid fingerprint digest type")); return -1; } if(!(pBIO = BIO_new(BIO_s_file()))) { LOG(X_ERROR("DTLS BIO_new failed for '%s': %s"), certPath, ERR_reason_error_string(ERR_get_error())); return -1; } if(rc >= 0 && BIO_read_filename(pBIO, certPath) != 1){ LOG(X_ERROR("DTLS BIO_read_filename failed for '%s': %s"), certPath, ERR_reason_error_string(ERR_get_error())); rc = -1; } if(rc >= 0 && !(pX509 = PEM_read_bio_X509(pBIO, NULL, 0, NULL))){ LOG(X_ERROR("DTLS PEM_read_bio_X509 failed for '%s': %s"), certPath, ERR_reason_error_string(ERR_get_error())); rc = -1; } lenHash = sizeof(pFingerprint->buf); if(rc >= 0 && (X509_digest(pX509, pEvp, pFingerprint->buf, &lenHash) != 1 || lenHash <= 0)) { LOG(X_ERROR("DTLS X509_digest failed for '%s': %s"), certPath, ERR_reason_error_string(ERR_get_error())); rc = -1; } else { pFingerprint->len = lenHash; rc = pFingerprint->len; } //avc_dumpHex(stderr, buf, sizeof(buf), 1); if(pX509) { X509_free(pX509); } if(pBIO) { BIO_free_all(pBIO); } return rc; }
int pktgen_GetLocalAdapterInfo(const char *dev, unsigned char *pmacaddr, in_addr_t *pnetaddr) { //#ifdef DISABLE_PCAP // return -1; //#else // DISABLE_PCAP IP_ADAPTER_INFO adapterInfo[10]; IP_ADAPTER_INFO *pAdapterInfo = NULL; unsigned long adaptersLen = sizeof(adapterInfo); unsigned int rc; memset(adapterInfo, 0, sizeof(adapterInfo)); if((rc = GetAdaptersInfo(adapterInfo, &adaptersLen)) != ERROR_SUCCESS) { LOG(X_ERROR("GetAdaptersInfo Failed with code: %d"), rc); return -1; } pAdapterInfo = adapterInfo; do { if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET) { if(!dev || (strstr(dev, pAdapterInfo->AdapterName) && pAdapterInfo->AddressLength == ETH_ALEN)) { if(pmacaddr) { memcpy(pmacaddr, pAdapterInfo->Address, ETH_ALEN); } if(pnetaddr) { if((*pnetaddr = inet_addr(pAdapterInfo->IpAddressList.IpAddress.String)) == INADDR_NONE) { LOG(X_ERROR("Cannot determinte IP address for adapter '%s'"), pAdapterInfo->AdapterName); return -1; } else if(dev || *pnetaddr != INADDR_ANY) { return 0; } } else { return 0; } } } pAdapterInfo = pAdapterInfo->Next; } while(pAdapterInfo); LOG(X_ERROR("Unable to find network adapter. None matching name '%s'"), dev ? dev : "<any>"); return -1; //#endif // DISABLE_PCAP }
int net_recvnb(SOCKET sock, unsigned char *buf, unsigned int len, unsigned int mstmt, int peek, int *pclosed) { struct timeval tv; fd_set fdsetRd; int rc; int sockflags = 0; #if !defined(__APPLE__) && !defined(WIN32) sockflags = MSG_NOSIGNAL; #endif // __APPLE__ if(sock == INVALID_SOCKET) { return -1; } if(peek) { sockflags |= MSG_PEEK; } if(pclosed) { *pclosed = 0; } tv.tv_sec = (mstmt / 1000); tv.tv_usec = (mstmt % 1000) * 1000; FD_ZERO(&fdsetRd); FD_SET(sock, &fdsetRd); if((rc = select(sock + 1, &fdsetRd, NULL, NULL, &tv)) > 0) { if((rc = recv(sock, (void *) buf, len, sockflags)) < 0) { LOG(X_ERROR("recv nonblock %d, sockflags: 0x%x returned %d "ERRNO_FMT_STR), len, sockflags, rc, ERRNO_FMT_ARGS); } else if(rc == 0) { LOG(X_WARNING("recv nonblock %d - connection has been closed."), len); if(pclosed) { *pclosed = 1; } // Do not return 0, since that is what select will return if timeout has expired return -1; } else { VSX_DEBUG_NET( LOG(X_DEBUG("NET - net_recvnb %s %d/%d bytes, fd: %d"), peek ? "peeked" : "got", rc, len, sock) ); } } else if(rc == 0) { //fprintf(stderr, "TMT EXPIRED sock:%d tv:%d,%d, mstmt:%d\n", sock, tv.tv_sec, tv.tv_usec, mstmt); // timeout expired } else { LOG(X_ERROR("select socket:%d returned: %d"), sock, rc); } return rc; }
static int mp4_extractAacAud(const MP4_CONTAINER_T *pMp4, const char *path, float fStart, float fDuration) { FILE_STREAM_T fStreamOut; MP4_TRAK_MP4A_T mp4BoxSet; ESDS_CBDATA_WRITE_SAMPLE_T esdsDescr; unsigned char buf[4096]; uint64_t startHz = 0; uint64_t durationHz = 0; int rc = 0; if(!pMp4|| !pMp4->pStream || pMp4->pStream == FILEOPS_INVALID_FP) { return -1; } LOG(X_DEBUG("Extracting aac audio from %s"), pMp4->pStream->cbGetName(pMp4->pStream)); esdsDescr.bs.buf = buf; esdsDescr.bs.sz = sizeof(buf); esdsDescr.bs.idx = 0; if(mp4_initMp4aTrack(pMp4, &mp4BoxSet) < 0) { return -1; } if(mp4BoxSet.pEsds->config.objtypeid != ESDS_OBJTYPE_MP4A) { LOG(X_ERROR("Unsupported mp4a esds object type descriptor: %u"), mp4BoxSet.pEsds->config.objtypeid); return -1; } else if(esds_decodeDecoderSp(mp4BoxSet.pEsds->specific.startcodes, (mp4BoxSet.pEsds->specific.type.length > sizeof(mp4BoxSet.pEsds->specific.startcodes) ? sizeof(mp4BoxSet.pEsds->specific.startcodes) : mp4BoxSet.pEsds->specific.type.length), &esdsDescr.decoderCfg) != 0) { LOG(X_ERROR("Failed to decode mp4a esds decoder specific data for type descriptor: %u"), mp4BoxSet.pEsds->config.type.descriptor); return -1; } durationHz = (uint64_t) (fDuration * mp4BoxSet.tk.pMdhd->timescale); startHz = (uint64_t) (fStart * mp4BoxSet.tk.pMdhd->timescale); if((fStreamOut.fp = fileops_Open(path, O_RDWR | O_CREAT)) == FILEOPS_INVALID_FP) { LOG(X_CRITICAL("Unable to open file for writing: %s"), path); return -1; } fStreamOut.offset = 0; esdsDescr.pStreamOut = &fStreamOut; rc = mp4_readSamplesFromTrack(&mp4BoxSet.tk, pMp4->pStream, esds_cbWriteSample_mp4wrap, &esdsDescr, startHz, durationHz); fileops_Close(fStreamOut.fp); return rc; }
static SILK_ENCODER_CODEC_CTXT_T *encoder_silk_alloc() { SILK_ENCODER_CODEC_CTXT_T *pSilk; SKP_int32 encSizeBytes; if(!(pSilk = (SILK_ENCODER_CODEC_CTXT_T *) calloc(1, sizeof(SILK_ENCODER_CODEC_CTXT_T)))) { return NULL; } if(encoder_load_dynamic(pSilk) < 0) { return NULL; } pSilk->pts = 0; //if(SKP_Silk_SDK_Get_Encoder_Size( &encSizeBytes ) != 0) { if(pSilk->fGetEncoderSize(&encSizeBytes) != 0) { LOG(X_ERROR("SKP_Silk_SDK_Get_Encoder_Size failed")); encoder_silk_free(pSilk); return NULL; } if(!(pSilk->psEnc = malloc(encSizeBytes))) { encoder_silk_free(pSilk); return NULL; } return pSilk; }
static MP4_CONTAINER_T *cap_http_mp4_open(const char *path, CAP_ASYNC_DESCR_T *pCapCfg) { MP4_CONTAINER_T *pMp4 = NULL; if(!path || !pCapCfg) { return NULL; } // // Used to open an mp4 container which may have an mdat box that is dynamically growing // //fprintf(stderr, "OPENING MP4 FOR STREAMING '%s'\n", path); if((pMp4 = mp4_open(path, 1)) == NULL) { LOG(X_ERROR("Failed to read downloaded mp4 path %s"), path); return NULL; } // // Change the read data file callback to handle the dynamically growing MDAT // pMp4->pStream->pUserData = pCapCfg; pMp4->pStream->cbRead = mp4_cbReadDataFileLive; pMp4->pStream->cbSeek = mp4_cbSeekDataFileLive; return pMp4; }
int dtls_netsock_setmtu(NETIO_SOCK_T *pnetsock, int mtu) { if(!pnetsock || !pnetsock->ssl.pCtxt) { return -1; } else if(mtu <= 0) { return 0; } else { #if defined(__linux__) if(mtu < 228) { LOG(X_ERROR("Cannot set DTLS MTU %d below minimum %d"), 228); return -1; } pthread_mutex_lock(&((STREAM_DTLS_CTXT_T *) pnetsock->ssl.pDtlsCtxt)->mtx); LOG(X_DEBUG("Setting DTLS MTU %d (netsock: 0x%x)"), mtu, pnetsock); // openSSL MTU may be broken on Mac, but may work on Linux //SSL_set_options(pnetsock->ssl.pCtxt, SSL_OP_NO_QUERY_MTU); //TODO: setting this makes the socket mtu 0, and the ssl/d1_both.c:268 assert crashes the app SSL_set_mtu(pnetsock->ssl.pCtxt, mtu); //SSL_set_mtu(pnetsock->ssl.pCtxt, mtu - 28); pthread_mutex_unlock(&((STREAM_DTLS_CTXT_T *) pnetsock->ssl.pDtlsCtxt)->mtx); #endif // (__linux__) return 0; } }
int flvsrv_cbWriteDataFile(void *pArg, const unsigned char *pData, unsigned int len) { int rc = 0; FLVSRV_CTXT_T *pFlvCtxt = (FLVSRV_CTXT_T *) pArg; //fprintf(stderr, "CB FLV RECORD len:%d\n", len); if(pFlvCtxt->recordFile.fp == FILEOPS_INVALID_FP) { if(capture_openOutputFile(&pFlvCtxt->recordFile, pFlvCtxt->overwriteFile, NULL) < 0) { // Do not call outfmt_removeCb since we're invoked from the cb thread //outfmt_removeCb(pFlvCtxt->pRecordOutFmt); pFlvCtxt->pRecordOutFmt->do_outfmt = 0; pFlvCtxt->pRecordOutFmt = NULL; return -1; } LOG(X_INFO("Created flv recording output file %s"), pFlvCtxt->recordFile.filename); } if((rc = WriteFileStream(&pFlvCtxt->recordFile, pData, len)) < 0) { LOG(X_ERROR("Failed to write flv %s %u bytes, total: %llu)"), (pFlvCtxt->writeErrDescr ? pFlvCtxt->writeErrDescr : ""), len, pFlvCtxt->totXmit); } else { pFlvCtxt->totXmit += len; } return rc; }
int flvsrv_record_start(FLVSRV_CTXT_T *pFlvCtxt, STREAMER_OUTFMT_T *pLiveFmt) { int rc = 0; unsigned int numQFull = 0; if(!pFlvCtxt || !pLiveFmt) { return -1; } // // Add a livefmt cb // pFlvCtxt->pRecordOutFmt = outfmt_setCb(pLiveFmt, flvsrv_addFrame, pFlvCtxt, &pLiveFmt->qCfg, NULL, 0, 0, &numQFull); if(pFlvCtxt->pRecordOutFmt) { if(flvsrv_init(pFlvCtxt, pLiveFmt->qCfg.growMaxPktLen) < 0) { return rc; } pFlvCtxt->cbWrite = flvsrv_cbWriteDataFile; LOG(X_INFO("Starting flvlive recording[%d] %d/%d to %s"), pFlvCtxt->pRecordOutFmt->cbCtxt.idx, numQFull + 1, pLiveFmt->max, pFlvCtxt->recordFile.filename); } else { LOG(X_ERROR("No flvlive recording resource available (max:%d)"), (pLiveFmt ? pLiveFmt->max : 0)); } return rc; }
int capture_parsePortStr(const char *str, uint16_t localPorts[], size_t maxLocalPorts, int noDup) { const char *p, *p2, *pdata; size_t numPortsAdded = 0; char buf[64]; int rc; p = str; while(p && numPortsAdded < maxLocalPorts) { if((p2 = strstr(p, ","))) { pdata = strutil_safe_copyToBuf(buf, sizeof(buf), p, p2); } else { pdata = p; } if((rc = addPorts(pdata, localPorts, &numPortsAdded, maxLocalPorts, noDup)) < 0) { LOG(X_ERROR("Invalid port specified in '%s'"), str); return rc; } if((p = p2)) { p++; } } return numPortsAdded; }
int flvsrv_send_vidframe(FLVSRV_CTXT_T *pFlvCtxt, const OUTFMT_FRAME_DATA_T *pFrame, int keyframe) { BYTE_STREAM_T bstmp; uint32_t timestamp32 = 0; unsigned char *pData = NULL; unsigned int lenData = 0; int rc; // // Compute the frame timestamp in ms, relative from the start // if(OUTFMT_PTS(pFrame) > pFlvCtxt->av.vid.tm0) { timestamp32 = (OUTFMT_PTS(pFrame) - pFlvCtxt->av.vid.tm0) / 90.0f; } //pFlvCtxt->av.vid.tmprev = timestamp32; // this may be wrong... tmprev is a 90KHz pts pFlvCtxt->out.prevtagidx = pFlvCtxt->out.bs.idx; memcpy(&bstmp, &pFlvCtxt->out.bs, sizeof(bstmp)); pFlvCtxt->out.bs.idx += FLV_TAG_HDR_SZ_NOPREV; if((rc = flvsrv_create_vidframe_h264(&pFlvCtxt->out.bs, &pFlvCtxt->av.vid, pFrame, NULL, NULL, keyframe)) < 0) { return rc; } pData = &pFlvCtxt->av.vid.tmpFrame.buf[pFlvCtxt->av.vid.tmpFrame.idx]; lenData = rc; //LOGHEX_DEBUG(pData, MIN(16, lenData)); //LOG(X_DEBUG("0x%x len:%d"), pData[4] & NAL_TYPE_MASK, lenData); if(pFlvCtxt->av.vid.tmpFrame.idx + lenData + 4 > pFlvCtxt->av.vid.tmpFrame.sz) { LOG(X_ERROR("flvsrv video frame size %d is too large for %d"), lenData, pFlvCtxt->av.vid.tmpFrame.sz); return -1; } pFlvCtxt->av.vid.tsLastWrittenFrame = timestamp32; // // Now that the data length is known, fill in the 11 byte flv header // flv_write_taghdr(&bstmp, FLV_TAG_VIDEODATA, lenData + pFlvCtxt->out.bs.idx - pFlvCtxt->out.prevtagidx - FLV_TAG_HDR_SZ_NOPREV, timestamp32); pFlvCtxt->writeErrDescr = "video header"; if((rc = pFlvCtxt->cbWrite(pFlvCtxt, pFlvCtxt->out.bs.buf, pFlvCtxt->out.bs.idx)) < 0) { return rc; } // // 4 byte previous tag size field // *((uint32_t *) &pData[lenData]) = htonl(lenData + pFlvCtxt->out.bs.idx - pFlvCtxt->out.prevtagidx); lenData += 4; pFlvCtxt->writeErrDescr = "video payload"; if((rc = pFlvCtxt->cbWrite(pFlvCtxt, pData, lenData)) < 0) { return rc; } return rc; }
int procdb_delete(SYS_PROCLIST_T *pProcs, const char *name, const char *id, int lock) { int rc = -1; SYS_PROC_T *pProc = NULL; SYS_PROC_T *pProcPrev = NULL; if(!pProcs || !name) { return -1; } if(!id) { id = ""; } if(lock) { pthread_mutex_lock(&pProcs->mtx); } pProc = pProcs->procs; while(pProc) { if(!strcasecmp(pProc->name, name) && !strcasecmp(pProc->id, id)) { if(pProcPrev) { pProcPrev->pnext = pProc->pnext; } if(pProcs->procs == pProc) { pProcs->procs = pProc->pnext; } LOG(X_DEBUG("Removing process '%s' pid:%d flags:0x%x"), pProc->name, pProc->pid, pProc->flags); if(pProcs->activeInstances > 0) { pProcs->activeInstances--; } if(pProc->isXcoded && pProcs->activeXcodeInstances > 0) { pProcs->activeXcodeInstances--; } free(pProc); rc = 0; break; } else { pProcPrev = pProc; pProc = pProc->pnext; } } if(lock) { pthread_mutex_unlock(&pProcs->mtx); } if(rc != 0) { LOG(X_ERROR("Failed to remove process '%s'"), pProc->name); } return rc; }
static int getSamplesInChunk(BOX_STSC_T *pStsc, unsigned int idxChunk, unsigned int *pidxStsc) { // // 1th based first chunk, samples per chunk, 1th based idx in stsd // { stsc[0]: 0x1 0x1e 0x1 , stsc[1]: 0xf2 0x3 0x1 } // if(*pidxStsc >= pStsc->entrycnt) { return -1; } if(pStsc->pEntries[*pidxStsc].sampledescidx != 1) { LOG(X_ERROR("stsc[%d].sampledescidx=%d (!= 1) not implemented!"), *pidxStsc, pStsc->pEntries[*pidxStsc].sampledescidx); return -1; } if(*pidxStsc < pStsc->entrycnt-1) { if(idxChunk >= pStsc->pEntries[(*pidxStsc) + 1].firstchunk - 1) { (*pidxStsc)++; } } return pStsc->pEntries[*pidxStsc].sampleperchunk; }
const STREAM_DEVICE_T *devtype_finddevice(const char *userAgent, int matchany) { const STREAM_DEVICE_T *pdev = NULL; if(!g_devtypes) { //devtype_init(); LOG(X_ERROR("Device database not configured")); return NULL; } pdev = g_devtypes; while(pdev) { // // if matchany is set, any default empty match can be made (last fall-thru device) // match & match2 is an 'and' based match // if(matchany || pdev->strmatch[0] != '\0' || pdev->strmatch[1] != '\0') { if(pdev->strmatch[0] == '\0' || (userAgent && strcasestr(userAgent, pdev->strmatch))) { if(pdev->strmatch2[0] == '\0' || (userAgent && strcasestr(userAgent, pdev->strmatch2))) { return pdev; } } } pdev = pdev->pnext; } if(matchany) { return pdev; } else { return NULL; } }
static int create_and_write_mpd(MPD_CREATE_CTXT_T *pCtxt, const MPD_ADAPTATION_T *pAdaptationList, DASH_MPD_TYPE_T mpdType, int outidx, int idxmax, unsigned int mediaSequenceIndex, int mediaSequenceMin) { int rc = 0; int idxbuf = 0; FILE_HANDLE fp; char buf[4096]; char mpdpath[VSX_MAX_PATH_LEN]; // // Create the .mpd xml file contents // if((idxbuf = mpd_doc_create(mpdType, pAdaptationList, pCtxt, outidx, mediaSequenceIndex, buf, sizeof(buf))) <= 0) { return -1; } // // Write the .mpd xml file to disk // if((rc = write_mpd_path(pCtxt, outidx, mpdType, mpdpath, sizeof(mpdpath))) < 0) { return rc; } if((fp = fileops_Open(mpdpath, O_RDWR | O_CREAT)) == FILEOPS_INVALID_FP) { LOG(X_ERROR("Failed to open DASH mpd '%s' for writing"), mpdpath); return -1; } if((rc = fileops_WriteBinary(fp, (unsigned char *) buf, idxbuf)) < 0) { LOG(X_ERROR("Failed to write %d to DASH mpd '%s'"), idxbuf, mpdpath); } fileops_Close(fp); if(rc >= 0) { LOG(X_DEBUG("Updated DASH playlist '%s' (%d - %d)"), mpdpath, mediaSequenceMin, idxmax); } else { LOG(X_ERROR("Failed to update DASH playlist '%s' (%d - %d)"), mpdpath, mediaSequenceMin, idxmax); } return rc; }
int strutil_convertDstStr(const char *dstArg, char dstHost[], size_t szHost, uint16_t dstPorts[], size_t numDstPorts, char dstUri[], size_t szUri) { int numPorts = 0; if(!dstArg) { LOG(X_ERROR("No destination host specified")); return -1; } else if((numPorts = getHostAndPorts(dstArg, dstHost, szHost, dstPorts, numDstPorts, 0, dstUri, szUri)) < 0) { return -1; } else if((numPorts == 0 || dstPorts[0] == 0) && inet_addr(dstHost) != INADDR_NONE) { LOG(X_ERROR("No destination port given")); return -1; } return numPorts; }
int xcode_frame_aud(IXCODE_AUDIO_CTXT_T *pIn, unsigned char *bufIn, unsigned int lenIn, unsigned char *bufOut, unsigned int lenOut) { XCODE_IPC_MEM_T *pMem; IXCODE_AUDIO_CTXT_T *pXcodeA; int rc, rcorig; if(!pIn->common.pIpc) { return -1; } pMem = ((XCODE_IPC_DESCR_T *) pIn->common.pIpc)->pmem; pXcodeA = &pMem->hdr.ctxt.aud; if(lenIn + lenOut > XCODE_IPC_MEM_DATASZ(pMem)) { LOG(X_ERROR("shared mem buffer size %d too small for %d + %d"), XCODE_IPC_MEM_DATASZ(pMem), lenIn, lenOut); return -1; } pXcodeA->common.inpts90Khz = pIn->common.inpts90Khz; pXcodeA->common.outpts90Khz = pIn->common.outpts90Khz; pXcodeA->common.decodeInIdx = pIn->common.decodeInIdx; pXcodeA->common.decodeOutIdx = pIn->common.decodeOutIdx; pXcodeA->common.encodeInIdx = pIn->common.encodeInIdx; pXcodeA->common.encodeOutIdx = pIn->common.encodeOutIdx; pXcodeA->pts = pIn->pts; // The following may not have been set during init //pXcodeA->cfgChannelsIn = pIn->cfgChannelsIn; //pXcodeA->cfgSampleRateIn = pIn->cfgSampleRateIn; if(bufIn) { memcpy(XCODE_IPC_MEM_DATA(pMem), bufIn, lenIn); } pMem->hdr.cmdrc = lenIn; pMem->hdr.offsetOut = lenIn; if((rc = rcorig = xcode_call_ipc(pIn->common.pIpc, XCODE_IPC_CMD_ENCODE_AUD)) != -1) { pIn->common.inpts90Khz = pXcodeA->common.inpts90Khz; pIn->common.outpts90Khz = pXcodeA->common.outpts90Khz; pIn->common.decodeInIdx = pXcodeA->common.decodeInIdx; pIn->common.decodeOutIdx = pXcodeA->common.decodeOutIdx; pIn->common.encodeInIdx = pXcodeA->common.encodeInIdx; pIn->common.encodeOutIdx = pXcodeA->common.encodeOutIdx; pIn->pts = pXcodeA->pts; if(rcorig > (int) (XCODE_IPC_MEM_DATASZ(pMem) - lenIn)) { rc = XCODE_IPC_MEM_DATASZ(pMem) - lenIn; LOG(X_WARNING("Encoded audio frame length truncated from %d to %d"), rcorig, rc); } else if(rc > (int) lenOut) { rc = lenOut; LOG(X_WARNING("Encoded audio frame length truncated from %d to %d"), rcorig, rc); } memcpy(bufOut, XCODE_IPC_MEM_DATA(pMem) + lenIn, rc); } return rc; }