static DIR_ENTRY_T *direntry_add(DIR_ENTRY_LIST_T **ppListArg, const DIR_ENTRY_T *pEntry) { DIR_ENTRY_LIST_T *pListNode = *ppListArg; DIR_ENTRY_LIST_T *pListNodePrev = NULL; while(1) { while(pListNode) { if(pListNode->pBuf == NULL) { pListNode->pBuf = (DIR_ENTRY_T *) avc_calloc(DIR_ENTRY_LIST_BUFNUM, sizeof(DIR_ENTRY_T)); pListNode->numAlloc = DIR_ENTRY_LIST_BUFNUM; } if(pListNode->num < pListNode->numAlloc) { memcpy(&pListNode->pBuf[pListNode->num], pEntry, sizeof(DIR_ENTRY_T)); pListNode->num++; return &pListNode->pBuf[pListNode->num - 1]; } pListNodePrev = pListNode; pListNode = pListNode->pnext; } pListNode = (DIR_ENTRY_LIST_T *) avc_calloc(1, sizeof(DIR_ENTRY_LIST_T)); if(pListNodePrev) { pListNodePrev->pnext = pListNode; } else { *ppListArg = pListNode; } } return NULL; }
SRV_CONF_T *conf_parse(const char *path) { FILE_HANDLE fp; SRV_CONF_T *pConf = NULL; KEYVAL_PAIR_T kv; KEYVAL_PAIR_T *pKv = NULL; KEYVAL_PAIR_T *pKvPrev = NULL; char buf[1024]; unsigned int numEntries = 0; if(!path) { return NULL; } if((fp = fileops_Open(path, O_RDONLY)) == FILEOPS_INVALID_FP) { LOG(X_CRITICAL("Unable to open file for reading: %s"), path); return NULL; } pConf = (SRV_CONF_T *) avc_calloc(1, sizeof(SRV_CONF_T)); while(fileops_fgets(buf, sizeof(buf) - 1, fp)) { if(conf_parse_keyval(&kv, buf, strlen(buf), '=', 0) > 0) { if((pKv = (KEYVAL_PAIR_T *) avc_calloc(1, sizeof(KEYVAL_PAIR_T))) == NULL) { LOG(X_CRITICAL("Failed to allocate %d"), sizeof(KEYVAL_PAIR_T)); break; } memcpy(pKv->key, kv.key, sizeof(pKv->key)); memcpy(pKv->val, kv.val, sizeof(pKv->val)); if(pKvPrev == NULL) { pConf->pKeyvals = pKv; } else { pKvPrev->pnext = pKv; } pKvPrev = pKv; numEntries++; } } fileops_Close(fp); return pConf; }
static MP4_CONTAINER_T *mp4net_open(CAP_HTTP_MP4_T *pCapCtxt) { MP4_CONTAINER_T *pMp4 = NULL; MP4_FILE_STREAM_T *pStream = NULL; // // Used to read an mp4 container directly from a network stream // if(!(pStream = avc_calloc(1, sizeof(MP4_FILE_STREAM_T)))) { return NULL; } pStream->cbRead = mp4_cbReadDataNet; pStream->cbSeek = mp4_cbSeekDataNet; pStream->cbClose = mp4_cbCloseDataNet; pStream->cbCheckFd = mp4_cbCheckFdDataNet; pStream->cbGetName = mp4_cbGetNameDataNet; pStream->cbNotifyType = mp4_cbNotifyType; pStream->pCbData = &pCapCtxt->mp4NetStream; if((pMp4 = mp4_createContainer()) == NULL) { pStream->cbClose(pStream); free(pStream); return NULL; } pMp4->pStream = pStream; //pMp4->proot->szdata = pMp4->pStream->size; pMp4->proot->subs = 1; return pMp4; }
int flvsrv_init(FLVSRV_CTXT_T *pFlv, unsigned int vidTmpFrameSz) { //int rc; pFlv->state = FLVSRV_STATE_INVALID; pFlv->cbWrite = flvsrv_cbWriteDataNet; pFlv->out.bs.sz = 1024; if((pFlv->out.bs.buf = (unsigned char *) avc_calloc(1, pFlv->out.bs.sz)) == NULL) { return -1; } if(vidTmpFrameSz == 0) { vidTmpFrameSz = STREAMER_RTMPQ_SZSLOT_MAX; } if((codecfmt_init(&pFlv->av, vidTmpFrameSz, 0)) < 0) { //pFlv->av.vid.tmpFrame.sz = vidTmpFrameSz; //if(!(pFlv->av.vid.tmpFrame.buf = (unsigned char *) avc_calloc(1, pFlv->av.vid.tmpFrame.sz))) { flvsrv_close(pFlv); return -1; } // // Enable queing up to 1 video frame - in the case where a keyframe is received, but no audio // start headers have yet been observed. Otherwise, the video would not start until the next // video keyframe after the audio start headers have been observed // pFlv->queuedFrames.max = 1; //pFlv->g_fd = open("test.flv", O_RDWR | O_CREAT, 0666); return 0; }
int cap_http_stream_mp4(CAP_ASYNC_DESCR_T *pCapCfg) { int rc = 0; MP4_CONTAINER_T *pMp4 = NULL; CAP_HTTP_MP4_STREAM_T *pCapHttpMp4Stream = NULL; PLAYLIST_MPD_ENTRY_T *pEntry = NULL; unsigned int idxUsed; pCapHttpMp4Stream = (CAP_HTTP_MP4_STREAM_T *) pCapCfg->pUserData; if(!pCapHttpMp4Stream) { return -1; } pCapHttpMp4Stream->pl.cbFreeEntry = cap_http_free_plentry; // // Wait until there is an output file to be processed // if(!(pEntry = cap_http_wait_for_next_mp4(pCapCfg))) { return 0; } // // Open the mp4 file path which is being stored int the 'tmp' directory // if(!(pMp4 = cap_http_mp4_open(pEntry->path, pCapCfg))) { mpdpl_free_entry(&pCapHttpMp4Stream->pl, pEntry); return -1; } pMp4->pNextLoader = avc_calloc(1, sizeof(MP4_LOADER_NEXT_T *)); pMp4->pNextLoader->cbLoadNextMp4 = cap_http_load_next_mp4; pMp4->pNextLoader->pCbData = pCapCfg; pEntry->pUserData = pMp4; //fprintf(stderr, "STREAM_MP4 begin offset:%llu, size:%llu, pStream:0x%x\n", pMp4->pStream->offset, pMp4->pStream->size, pMp4->pStream); // // The stream_mp4 should not return until the entire playlist is processed // rc = stream_mp4(pMp4, pCapCfg->pStreamerCfg); //fprintf(stderr, "STREAM_MP4 END rc:%d\n", rc); // // Free the popped playlist entry // mpdpl_free_entry(&pCapHttpMp4Stream->pl, pEntry); for(idxUsed = 0; idxUsed < sizeof(pCapHttpMp4Stream->plUsed) / sizeof(pCapHttpMp4Stream->plUsed[0]); idxUsed++) { if(pCapHttpMp4Stream->plUsed[idxUsed].plEntryUsed) { mpdpl_free_entry(&pCapHttpMp4Stream->pl, pCapHttpMp4Stream->plUsed[idxUsed].plEntryUsed); pCapHttpMp4Stream->plUsed[idxUsed].plEntryUsed = NULL; } } return rc; }
int mpd_init(MPD_CREATE_CTXT_T *pCtxt, const DASH_INIT_CTXT_T *pDashInitCtxt, const CODEC_AV_CTXT_T *pAvCtxt) { unsigned int indexCount; unsigned int idx; int rc = 0; if(!pCtxt || !pDashInitCtxt) { return -1; } memcpy(&pCtxt->init, pDashInitCtxt, sizeof(pCtxt->init)); if(!pCtxt->init.outfileprefix || pCtxt->init.outfileprefix[0] == '\0') { pCtxt->init.outfileprefix = DASH_DEFAULT_NAME_PRFX; } pCtxt->active = 1; pCtxt->cbFormatPathPrefix = mpd_format_path_prefix; pCtxt->pAvCtxt = pAvCtxt; pCtxt->outdir = pDashInitCtxt->outdir; if(!pCtxt->init.outfilesuffix) { pCtxt->init.outfilesuffix = DASH_DEFAULT_SUFFIX_M4S; } pCtxt->mpdOutputTypes[0].type = pDashInitCtxt->dash_mpd_type; pCtxt->mpdOutputTypes[1].type = DASH_MPD_TYPE_INVALID; if((indexCount = pCtxt->init.indexcount) == 0) { indexCount = DASH_NUM_MEDIA_FILES_DEFAULT; } else if(indexCount < DASH_NUM_MEDIA_FILES_MIN) { indexCount = DASH_NUM_MEDIA_FILES_MIN; } else if(indexCount > DASH_NUM_MEDIA_FILES_MAX) { indexCount = DASH_NUM_MEDIA_FILES_MAX; } for(idx = 0; idx < DASH_MPD_MAX_ADAPTATIONS; idx++) { if(!(pCtxt->segs[idx].pSegments = (MPD_SEGMENT_ENTRY_T *) avc_calloc(indexCount, sizeof(MPD_SEGMENT_ENTRY_T)))) { return -1; } pCtxt->segs[idx].curIdx = 0; pCtxt->segs[idx].indexInSegments = 0; pCtxt->segs[idx].indexCount = indexCount; } pCtxt->outidxTot = 1; // // Count the number of active outputs // for(idx = 1; idx < IXCODE_VIDEO_OUT_MAX; idx ++) { if(pCtxt->pAvCtxt->vid.pStreamerCfg->xcode.vid.out[idx].active) { pCtxt->outidxTot++; } } return rc; }
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 codecfmt_init(CODEC_AV_CTXT_T *pAv, unsigned int vidTmpFrameSz, unsigned int audTmpFrameSz) { if(vidTmpFrameSz > 0) { pAv->vid.tmpFrame.sz = vidTmpFrameSz; if((pAv->vid.tmpFrame.buf = (unsigned char *) avc_calloc(1, pAv->vid.tmpFrame.sz)) == NULL) { codecfmt_close(pAv); return -1; } } if(audTmpFrameSz > 0) { pAv->aud.tmpFrame.sz = audTmpFrameSz; if((pAv->aud.tmpFrame.buf = (unsigned char *) avc_calloc(1, pAv->aud.tmpFrame.sz)) == NULL) { codecfmt_close(pAv); return -1; } } return 0; }
static int cbparse_entry_rtspua(void *pArg, const char *p) { STREAM_RTSP_SESSIONS_T *pRtsp = (STREAM_RTSP_SESSIONS_T *) pArg; size_t sz; int rc = 0; if(pRtsp->rtspForceTcpUAList.count >= RTSP_FORCE_TCP_UA_LIST_MAX) { return 0; } if((p = avc_dequote(p, NULL, 0))) { sz = strlen(p); if(!(pRtsp->rtspForceTcpUAList.arr[pRtsp->rtspForceTcpUAList.count] = (char *) avc_calloc(1, sz + 1))) { return -1; } memcpy(pRtsp->rtspForceTcpUAList.arr[pRtsp->rtspForceTcpUAList.count++], p, sz); } return rc; }
static STREAM_DEVICE_T *create_device(const char *name, const char *strmatch, const char *strmatch2, enum STREAM_METHOD methods[], enum STREAM_DEVICE_TYPE devtype) { STREAM_DEVICE_T *dev; if(!(dev = avc_calloc(1, sizeof(STREAM_DEVICE_T)))) { return NULL; } strncpy((char *) dev->name, name, sizeof(dev->name) - 1); strncpy((char *) dev->strmatch, strmatch, sizeof(dev->strmatch) - 1); if(strmatch2 && strmatch2[0] != '\0') { strncpy((char *) dev->strmatch2, strmatch2, sizeof(dev->strmatch2) - 1); } memcpy(dev->methods, methods, sizeof(enum STREAM_METHOD) * STREAM_DEVICE_METHODS_MAX); dev->devtype = devtype; return dev; }
int pool_open(POOL_T *pPool, unsigned int numElements, unsigned int szElement, int lock) { unsigned int idx = 0; POOL_ELEMENT_T *pCur, *pPrev; if(!pPool || numElements <= 0 || szElement <= 0) { return -1; } if(!(pPool->pElements = (POOL_ELEMENT_T *) avc_calloc(numElements, szElement))) { return -1; } pPool->lock = lock; pPool->szElement = szElement; pPool->numElements = numElements; pPool->pInUse = NULL; pPool->freeElements = numElements; pPool->destroy_onempty = 0; for(idx = 0; idx < numElements; idx++) { pCur = (POOL_ELEMENT_T *) (((char *) pPool->pElements) + (idx * szElement)); pCur->id = idx + 1; if(idx == 0) { pPool->pFree = pPool->pElements; } else { //pCur = (POOL_ELEMENT_T *) (((char *) pPool->pElements) + (idx * szElement)); pPrev = (POOL_ELEMENT_T *) (((char *) pPool->pElements) + ((idx - 1) * szElement)); pPrev->pNext = pCur; pCur->pPrev = pPrev; } } if(pPool->lock) { pthread_mutex_init(&pPool->mtx, NULL); } return 0; }
XCODE_IPC_DESCR_T *xcode_ipc_open(unsigned int sz, key_t key) { XCODE_IPC_DESCR_T *pIpc = NULL; pIpc = avc_calloc(1, sizeof(XCODE_IPC_DESCR_T)); pIpc->sz = sz; if((pIpc->hFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, XCODE_FILE_MAPPING_NAME)) == NULL) { LOG(X_ERROR("OpenFileMapping %s failed (error:%d)"), XCODE_FILE_MAPPING_NAME, GetLastError()); xcode_ipc_close(pIpc); return NULL; } if((pIpc->pmem = MapViewOfFile(pIpc->hFile, FILE_MAP_ALL_ACCESS, 0, 0, pIpc->sz)) == NULL) { LOG(X_ERROR("MapViewOfFile %s failed (error:%d)"), XCODE_FILE_MAPPING_NAME, GetLastError()); xcode_ipc_close(pIpc); return NULL; } if((pIpc->hSemSrv = OpenSemaphoreA(SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, FALSE, XCODE_SEM_SRV_NAME)) == NULL) { LOG(X_ERROR("OpenSemaphore %s failed (error:%d)"), XCODE_SEM_SRV_NAME, GetLastError()); xcode_ipc_close(pIpc); return NULL; } if((pIpc->hSemCli = OpenSemaphoreA(SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, FALSE, XCODE_SEM_CLI_NAME)) == NULL) { LOG(X_ERROR("OpenSemaphore %s failed (error:%d)"), XCODE_SEM_CLI_NAME, GetLastError()); xcode_ipc_close(pIpc); return NULL; } pIpc->pmem->hdr.cmd = XCODE_IPC_CMD_NONE; return pIpc; }
MP4_EXTRACT_STATE_T *mp4_create_extract_state(const MP4_CONTAINER_T *pMp4, const MP4_TRAK_T *pTrak) { MP4_EXTRACT_STATE_T *pExtractSt = NULL; if(!(pExtractSt = (MP4_EXTRACT_STATE_T *) avc_calloc(1, sizeof(MP4_EXTRACT_STATE_T)))) { return NULL; } memcpy(&pExtractSt->trak, pTrak, sizeof(MP4_TRAK_T)); pExtractSt->cur.pExtSt = pExtractSt; pExtractSt->start.pExtSt = pExtractSt; pExtractSt->lastSync.pExtSt = pExtractSt; pExtractSt->pStream = pMp4->pStream; // // Make a copy of the next loader callback context, which is owned by the mp4 container // if(pMp4->pNextLoader) { memcpy(&pExtractSt->nextLoader, pMp4->pNextLoader, sizeof(pExtractSt->nextLoader)); } // preserve the pNextLoader return pExtractSt; }
static int readFramesSetup(CAPTURE_FILTER_T *pFilter, PKTQUEUE_PKT_T *pFrame) { unsigned int prebufOffset = 0; unsigned int bpp = 0; if(pFilter->pCapAction && pFilter->pCapAction->pQueue) { prebufOffset = pFilter->pCapAction->pQueue->cfg.prebufOffset; } if((bpp = codecType_getBitsPerPx(pFilter->mediaType)) <= 0) { LOG(X_ERROR("Unsupported raw device format %s (%d)"), codecType_getCodecDescrStr(pFilter->mediaType), pFilter->mediaType); return -1; } memset(pFrame, 0, sizeof(PKTQUEUE_PKT_T)); pFrame->allocSz = (pFilter->width * pFilter->height * bpp / 8); if(!(pFrame->pBuf = (unsigned char *) avc_calloc(1, prebufOffset + pFrame->allocSz))) { return -1; } pFrame->pData = pFrame->pBuf + prebufOffset; pFrame->len = pFrame->allocSz; return 0; }
SESSION_DESCR_T *session_add(SESSION_CACHE_T *pCache, struct sockaddr *pSockAddr) { SESSION_DESCR_T *pSession = NULL; SESSION_DESCR_T *pSessionPrev = NULL; unsigned int numSessions = 0; char tmp[128]; //TODO: need a hash while(pSession) { if(pSession->cookie[0] == '\0') { break; } numSessions++; pSessionPrev = pSession; pSession = pSession->pnext; } if(!pSession) { if(numSessions < SESSION_CACHE_MAX) { pSession = avc_calloc(1, sizeof(SESSION_DESCR_T)); if(pSessionPrev) { pSessionPrev->pnext = pSession; } else { pCache->plist = pSession; } } else { LOG(X_WARNING("No available session for %s:%d"), FORMAT_NETADDR(*pSockAddr, tmp, sizeof(tmp)), ntohs(PINET_PORT(pSockAddr))); return NULL; } } pSession->lastTm = time(NULL); return pSession; }
int image_open(const char *path, IMAGE_GENERIC_DESCR_T *pImg, enum MEDIA_FILE_TYPE mediaType) { int rc = 0; uint32_t sz; FILE_STREAM_T fs; if(!path || !pImg) { return -1; } pImg->mediaType = mediaType; memset(&fs, 0, sizeof(fs)); if(OpenMediaReadOnly(&fs, path) < 0) { return -1; } if(fs.size > IMAGE_MAX_SIZE) { LOG(X_ERROR("File %s size %llu exceeds max %d"), fs.filename, fs.size, IMAGE_MAX_SIZE); rc = -1; } else if(fs.size < 4) { LOG(X_ERROR("File %s size is too small %llu"), fs.filename, fs.size); rc = -1; } if(rc >= 0) { memset(&pImg->bs, 0, sizeof(pImg->bs)); pImg->bs.sz = (unsigned int) fs.size; if(!(pImg->bs.buf = avc_calloc(1, pImg->bs.sz))) { rc = -1; } } if(rc >= 0) { while(pImg->bs.idx < fs.size) { if((sz = (uint32_t) (fs.size - pImg->bs.idx)) > 4096) { sz = 4096; } if((rc = ReadFileStream(&fs, &pImg->bs.buf[pImg->bs.idx], sz)) != sz) { rc = -1; break; } pImg->bs.idx += rc; } if(rc >= 0) { rc = pImg->bs.idx; } pImg->bs.idx = 0; } CloseMediaFile(&fs); pImg->width = 0; pImg->height = 0; if(rc >= 0) { switch(mediaType) { case MEDIA_FILE_TYPE_PNG: png_parse(pImg); break; case MEDIA_FILE_TYPE_BMP: bmp_parse_hdr(pImg); break; default: break; } } return rc; }
int metafile_open(const char *path, META_FILE_T *pMetaFile, int readIgnores, int readTitles) { int rc = 0; FILE_HANDLE fp; char *p; int match = 0; PARSE_ENTRY_DATA_T parseData; ENTRY_IGNORE_T *pIgnore; ENTRY_IGNORE_T *pIgnorePrev = NULL; ENTRY_META_DESCRIPTION_T *pDesc; ENTRY_META_DESCRIPTION_T *pDescPrev = NULL; char buf[1024]; if(!path || !pMetaFile) { return -1; } if((fp = fileops_Open(path, O_RDONLY)) == FILEOPS_INVALID_FP) { LOG(X_ERROR("Unable to open metafile for reading: %s (ignore list:%d)"), path, readIgnores); return -1; } VSX_DEBUG_METAFILE( LOG(X_DEBUG("META - metafile_open: '%s', readIgnores: %d, readTitles: %d"), path, readIgnores, readTitles)); pMetaFile->filestr[0] = '\0'; pMetaFile->linkstr[0] = '\0'; pMetaFile->instr[0] = '\0'; pMetaFile->xcodestr[0] = '\0'; pMetaFile->userpass[0] = '\0'; pMetaFile->methodBits = 0; memset(&parseData, 0, sizeof(parseData)); parseData.path = path; while(fileops_fgets(buf, sizeof(buf) - 1, fp)) { parseData.linenum++; p = buf; while(*p == ' ' || *p == '\t') { p++; } if(*p == '#' || *p == '\r' || *p == '\n') { continue; } // // Reset the parse context storage // reset_parsedata_ctxt(&parseData); // // We allow multiple configuration items on one line, separated by comma // rc = strutil_parse_csv(cbparse_entry_metafile, &parseData, p); if(parseData.flags == 0) { continue; } if(!(readIgnores || readTitles)) { handle_parsed_line(&parseData, pMetaFile, path, &match); } // // We're only interested in reading the ignore list // if(readIgnores && parseData.ignore[0] != '\0') { if(!(pIgnore = (ENTRY_IGNORE_T *) avc_calloc(1, sizeof(ENTRY_IGNORE_T)))) { rc = -1; break; } strncpy(pIgnore->filename, parseData.ignore, sizeof(pIgnore->filename)); if(pIgnorePrev) { pIgnorePrev->pnext = pIgnore; } else { pMetaFile->pignoreList = pIgnore; } pIgnorePrev = pIgnore; } // // We're only interested in reading the resource title name // if(readTitles && parseData.title[0] != '\0' && parseData.filename[0] != '\0') { if(!(pDesc = (ENTRY_META_DESCRIPTION_T *) avc_calloc(1, sizeof(ENTRY_META_DESCRIPTION_T)))) { rc = -1; break; } strncpy(pDesc->title, parseData.title, sizeof(pDesc->title)); strncpy(pDesc->filename, parseData.filename, sizeof(pDesc->filename)); if(pDescPrev) { pDescPrev->pnext = pDesc; } else { pMetaFile->pDescriptionList = pDesc; } pDescPrev = pDesc; } } fileops_Close(fp); VSX_DEBUG_METAFILE( LOG(X_DEBUG("META - metafile_open done '%s', meta-devicefilter:'%s', meta-profilefilter: '%s' returning rc: %d, " "file: '%s', link: '%s', input: '%s', xcode: '%s', digestauth: '%s', methods: '%s', id: '%s'" ), path, pMetaFile->devicefilterstr, pMetaFile->profilefilterstr, rc, pMetaFile->filestr, pMetaFile->linkstr, pMetaFile->instr, pMetaFile->xcodestr, pMetaFile->userpass, devtype_dump_methods(pMetaFile->methodBits, buf, sizeof(buf)), pMetaFile->id)); return rc; }
int mp4_extractRaw(const MP4_CONTAINER_T *pMp4, const char *outPrfx, float fStart, float fDuration, int overwrite, int extractVid, int extractAud) { BOX_HDLR_T *pBoxHdlr; BOX_T *pBoxTrak; BOX_T *pBox; MP4_TRAK_T mp4Trak; char *outPath = NULL; size_t szPath; FILE_HANDLE fp; int rc = 0; if(!pMp4|| !pMp4->pStream || !pMp4->pStream->cbCheckFd(pMp4->pStream) || !outPrfx) { return -1; } else if(!extractVid && !extractAud) { return -1; } if(!(pBoxTrak = mp4_findBoxInTree(pMp4->proot, *((uint32_t *) "moov"))) || !(pBoxTrak = pBoxTrak->child)) { LOG(X_ERROR("No tracks found in mp4")); return -1; } while(pBoxTrak) { if(pBoxTrak->type != *((uint32_t *) "trak") || !(pBoxHdlr = (BOX_HDLR_T *) mp4_findBoxInTree(pBoxTrak, *((uint32_t *) "hdlr")))) { pBoxTrak = pBoxTrak->pnext; continue; } memset(&mp4Trak, 0, sizeof(MP4_TRAK_T)); mp4Trak.pTrak = pBoxTrak; pBox = fillTrack(&mp4Trak, 0); if(!pBox) { pBoxTrak = pBoxTrak->pnext; continue; } szPath = strlen(outPrfx); outPath = (char *) avc_calloc(1, szPath + 8); memcpy(outPath, outPrfx, szPath); rc = 0; if(pBoxHdlr->handlertype == *((uint32_t *) "soun") || pBoxHdlr->handlertype == *((uint32_t *) "sdsm")) { if(extractAud) { if(mp4_findBoxInTree(pBoxTrak, *((uint32_t *) "mp4a"))) { strncpy(&outPath[szPath], ".aac", 7); } else { LOG(X_WARNING("Unknown audio track %c%c%c%c written as raw output"), ((unsigned char *)&pBox->type)[0], ((unsigned char *)&pBox->type)[1], ((unsigned char *)&pBox->type)[2], ((unsigned char *)&pBox->type)[3]); strncpy(&outPath[szPath], ".araw", 7); } } else { pBox = NULL; } } else if(pBoxHdlr->handlertype == *((uint32_t *) "vide")) { if(extractVid) { if(mp4_findBoxInTree(pBoxTrak, *((uint32_t *) "avc1"))) { strncpy(&outPath[szPath], ".h264", 7); } else if(mp4_findBoxInTree(pBoxTrak, *((uint32_t *) "mp4v"))) { strncpy(&outPath[szPath], ".mpg4", 7); } else { LOG(X_WARNING("Unknown video track %c%c%c%c written as raw output"), ((unsigned char *)&pBox->type)[0], ((unsigned char *)&pBox->type)[1], ((unsigned char *)&pBox->type)[2], ((unsigned char *)&pBox->type)[3]); strncpy(&outPath[szPath], ".vraw", 7); } } else { pBox = NULL; } } else { pBox = NULL; } if(pBox) { if(!overwrite && (fp = fileops_Open(outPath, O_RDONLY)) != FILEOPS_INVALID_FP) { fileops_Close(fp); LOG(X_ERROR("File %s already exists. Will not overwrite."), outPath); free(outPath); pBoxTrak = pBoxTrak->pnext; continue; } if(pBox->type == *((uint32_t *) "avc1")) { rc = mp4_extractAvcVid(pMp4, outPath, fStart, fDuration); } else if(pBox->type == *((uint32_t *) "mp4v")) { rc = mp4_extractMp4Vid(pMp4, outPath, fStart, fDuration); } else if(pBox->type == *((uint32_t *) "mp4a")) { rc = mp4_extractAacAud(pMp4, outPath, fStart, fDuration); } else { rc = extractGenericTrak(pMp4, &mp4Trak, outPath, fStart, fDuration); } if(rc == 0) { LOG(X_INFO("Created %s"), outPath); } free(outPath); } pBoxTrak = pBoxTrak->pnext; } return rc; }
RTSP_HTTP_SESSION_T *rtspsrv_newHttpSession(STREAM_RTSP_SESSIONS_T *pRtsp, const char *sessionCookie, const struct sockaddr *psa) { RTSP_HTTP_SESSION_T *pRtspGetSession = NULL; size_t szCookie; unsigned int idx; if(!pRtsp || !pRtsp->pRtspGetSessionsBuf || !sessionCookie || sessionCookie[0] == '\0') { return NULL; } if((szCookie = strlen(sessionCookie)) > RTSP_HTTP_SESSION_COOKIE_MAX - 1) { LOG(X_ERROR("Client RTSP HTTP session cookie length %d exceeds %d"), szCookie, RTSP_HTTP_SESSION_COOKIE_MAX - 1); return NULL; } pthread_mutex_lock(&pRtsp->mtx); for(idx = 0; idx < pRtsp->numRtspGetSessions; idx++) { if(!pRtsp->pRtspGetSessionsBuf[idx].inuse) { pRtspGetSession = &pRtsp->pRtspGetSessionsBuf[idx]; if(!pRtspGetSession->pRequestBufWr) { if(!(pRtspGetSession->pRequestBufWr = (char *) avc_calloc(2, RTSP_HTTP_POST_BUFFER_SZ))) { pthread_mutex_unlock(&pRtsp->mtx); return NULL; } pRtspGetSession->pRequestBufRd = pRtspGetSession->pRequestBufWr + RTSP_HTTP_POST_BUFFER_SZ; pthread_mutex_init(&pRtspGetSession->cond.mtx, NULL); pthread_cond_init(&pRtspGetSession->cond.cond, NULL); pthread_mutex_init(&pRtspGetSession->mtx, NULL); } pRtspGetSession->inuse = 1; memset(&pRtspGetSession->netsocketPost, 0, sizeof(pRtspGetSession->netsocketPost)); NETIOSOCK_FD(pRtspGetSession->netsocketPost) = INVALID_SOCKET; pRtspGetSession->expired = 0; strncpy(pRtspGetSession->cookie.sessionCookie, sessionCookie, RTSP_HTTP_SESSION_COOKIE_MAX - 1); if(psa) { memcpy(&pRtspGetSession->cookie.sa, psa, INET_SIZE(*psa)); } gettimeofday(&pRtspGetSession->tvCreate, NULL); pRtspGetSession->tvLastMsg.tv_sec = 0; pRtspGetSession->requestSz = 0; pRtspGetSession->requestIdxWr = 0; pRtspGetSession->pRequestBufWr[0] = '\0'; pRtspGetSession->pRequestBufRd[0] = '\0'; pRtspGetSession->pnext = NULL; if(pRtsp->pRtspGetSessionsTail) { pRtsp->pRtspGetSessionsTail->pnext = pRtspGetSession; } else { pRtsp->pRtspGetSessionsHead = pRtspGetSession; } pRtsp->pRtspGetSessionsTail = pRtspGetSession; break; } } pthread_mutex_unlock(&pRtsp->mtx); return pRtspGetSession; }
int rtspsrv_init(STREAM_RTSP_SESSIONS_T *pRtsp) { pthread_t ptdMonitor; struct sockaddr_storage sa; pthread_attr_t attrMonitor; RTSP_MONITOR_CTXT_T startCtxt; const char *s; if(!pRtsp || pRtsp->max <= 0) { return -1; } if(pRtsp->psessions) { avc_free((void *) &pRtsp->psessions); } destroy_rtspgetsessions(pRtsp); if(!(pRtsp->psessions = (RTSP_SESSION_T *) avc_calloc(pRtsp->max, sizeof(RTSP_SESSION_T)))) { return -1; } pRtsp->numRtspGetSessions = pRtsp->max * 2; if(!(pRtsp->pRtspGetSessionsBuf = (RTSP_HTTP_SESSION_T *) avc_calloc(pRtsp->numRtspGetSessions, sizeof(RTSP_HTTP_SESSION_T)))) { avc_free((void *) &pRtsp->psessions); pRtsp->numRtspGetSessions = 0; return -1; } pthread_mutex_init(&pRtsp->mtx, NULL); // // If all UDP / RTP sockets are bound to the same port then establish // the listener of this port prior to any RTSP interaction because some app // gateways may send some UDP polling data to the base port - and returning // an ICMP port unreachable would prevent such app gateways from allocating // UDP proxy ports // pRtsp->sockStaticLocalPort = INVALID_SOCKET; if(pRtsp->staticLocalPort > 0) { memset(&sa, 0, sizeof(sa)); sa.ss_family = AF_INET; ((struct sockaddr_in *) &sa)->sin_addr.s_addr = INADDR_ANY; INET_PORT(sa) = htons(pRtsp->staticLocalPort); if((pRtsp->sockStaticLocalPort = net_opensocket(SOCK_DGRAM, 0, 0, (struct sockaddr *) &sa)) == INVALID_SOCKET) { LOG(X_ERROR("Failed to open RTSP static local RTP port %d"), pRtsp->staticLocalPort); } else { if(net_setsocknonblock(pRtsp->sockStaticLocalPort, 1) < 0) { LOG(X_ERROR("Failed to listen on RTSP static local RTP port %d"), pRtsp->staticLocalPort); net_closesocket(&pRtsp->sockStaticLocalPort); } } //if(pRtsp->sockStaticLocalPort != INVALID_SOCKET) { // sain.sin_addr.s_addr = inet_addr("127.0.0.1"); // rc = sendto(pRtsp->sockStaticLocalPort, &sain, 1, 0, (struct sockaddr *) &sain, sizeof(sain)); // fprintf(stderr, "SENDTO:%d\n", rc); //} } // // Parse any CSV of quoted User-Agent matches which should try to force TCP interleaved mode // pRtsp->rtspForceTcpUAList.count = 0; if(pRtsp->rtspForceTcpUAList.str) { strutil_parse_csv(cbparse_entry_rtspua, pRtsp, pRtsp->rtspForceTcpUAList.str); } pRtsp->runMonitor = 2; memset(&startCtxt, 0, sizeof(startCtxt)); startCtxt.pRtsp = pRtsp; if((s = logutil_tid_lookup(pthread_self(), 0)) && s[0] != '\0') { snprintf(startCtxt.tid_tag, sizeof(startCtxt.tid_tag), "%s-rtspmon", s); } pthread_attr_init(&attrMonitor); pthread_attr_setdetachstate(&attrMonitor, PTHREAD_CREATE_DETACHED); if(pthread_create(&ptdMonitor, &attrMonitor, (void *) rtsp_monitor_proc, (void *) &startCtxt) != 0) { LOG(X_ERROR("Unable to create RTP monitor thread")); pRtsp->runMonitor = 0; if(pRtsp->psessions) { avc_free((void *) &pRtsp->psessions); } destroy_rtspgetsessions(pRtsp); pthread_mutex_destroy(&pRtsp->mtx); } while(pRtsp->runMonitor != 1 && pRtsp->runMonitor != -1) { usleep(5000); } return 0; }
DIR_ENTRY_LIST_T *direntry_getentries(const MEDIADB_DESCR_T *pMediaDb, const char *dir, const char *fidxdir, const char *searchstr, int includedirs, unsigned int startidx, unsigned int max, enum DIR_SORT sort) { DIR *pdir; int rc = 0; struct dirent *direntry; char path[VSX_MAX_PATH_LEN]; struct stat st; int addEntry; FILE_LIST_T fileList; FILE_LIST_ENTRY_T *pFileEntry = NULL; META_FILE_T metaFile; DIR_ENTRY_LIST_T *pEntryList = NULL; DIR_ENTRY_T entry; DIR_ENTRY_T *pEntry; const char *pdispname; unsigned int idx = 0; unsigned int cnt = 0; unsigned int cntInDir = 0; COMPARE_DIR_ENTRY compareFunc = direntry_getcompfunc(sort); VSX_DEBUG_MGR( LOG(X_DEBUG("MGR - direntry_getentries dir: '%s', fidxdir: '%s', searchstr: '%s', " "includedirs: %d, startidx: %d, max: %d"), dir, fidxdir, searchstr, includedirs, startidx, max)); if(!(pdir = fileops_OpenDir(dir))) { return NULL; } memset(&fileList, 0, sizeof(fileList)); if(fidxdir) { file_list_read(fidxdir, &fileList); } // // Read the directory wide metafile to get a list of 'ignore' entries // memset(&metaFile, 0, sizeof(metaFile)); mediadb_prepend_dir(dir, METAFILE_DEFAULT, path, sizeof(path)); if(fileops_stat(path, &st) == 0) { metafile_open(path, &metaFile, 1, 1); } while((direntry = fileops_ReadDir(pdir))) { VSX_DEBUG_MGR( LOG(X_DEBUGV("MGR - direntry_getentries d_name: '%s', isdir: %d"), direntry->d_name, (direntry->d_type & DT_DIR)) ); if(is_entry_ignored(metaFile.pignoreList, direntry->d_name)) { continue; } if(!(pdispname = find_entry_description(metaFile.pDescriptionList, direntry->d_name))) { pdispname = direntry->d_name; } if(searchstr && !is_match_search(pdispname, NULL, searchstr)) { continue; } memset(&entry, 0, sizeof(entry)); strncpy(entry.d_name, direntry->d_name, sizeof(entry.d_name) - 1); if(pdispname != direntry->d_name) { strncpy(entry.displayname, pdispname, sizeof(entry.displayname) - 1); } entry.d_type = direntry->d_type; addEntry = 0; if(direntry->d_type & DT_DIR) { if(includedirs && mediadb_isvalidDirName(pMediaDb, direntry->d_name)) { addEntry = 1; } } else if(mediadb_isvalidFileName(pMediaDb, direntry->d_name, 1, 1)) { mediadb_prepend_dir(dir, direntry->d_name, path, sizeof(path)); if(fileops_stat(path, &st) == 0) { entry.size = st.st_size; //entry.tm = st.st_mtime; entry.tm = st.st_ctime; if(fidxdir && (pFileEntry = file_list_find(&fileList, direntry->d_name))) { entry.numTn = pFileEntry->numTn; entry.duration = pFileEntry->duration; } addEntry = 1; } } if(addEntry) { VSX_DEBUG_MGR( LOG(X_DEBUGV("MGR - direntry_getentries add d_name: '%s', isdir: %d"), direntry->d_name, (direntry->d_type & DT_DIR)) ); if(compareFunc || (idx >= startidx && (max == 0 || cnt < max))) { if(cnt >= DIR_ENTRY_LIST_BUFNUM) { LOG(X_WARNING("Not showing more than %d entries in %s"), cnt, dir); break; } else if(!(pEntry = direntry_addsorted(&pEntryList, &entry, compareFunc))) { LOG(X_ERROR("Failed to add directory entry '%s' to list"), direntry->d_name); rc = -1; break; } cnt++; } idx++; cntInDir++; } } // // Since when a sort is requested we have to sort every entry in the directory. Now we can move the head pointer // to the first desired entry // if(pEntryList && compareFunc && startidx > 0) { pEntry = pEntryList->pHead; for(idx = 0; idx < startidx; idx++) { pEntry = pEntry->pnext; cnt--; } pEntryList->pHead = pEntry; if(cnt > max) { cnt = max; } //fprintf(stderr, "moved phead to %s, cnt:%d, cntInDir:%d\n", pEntryList->pHead ? pEntryList->pHead->d_name : NULL, cnt, cntInDir); } fileops_CloseDir(pdir); if(fidxdir) { file_list_close(&fileList); } metafile_close(&metaFile); if(rc == 0 && !pEntryList) { // If the user requested an index out of bounds, return an empty list with // a valid cntTotalInDir pEntryList = (DIR_ENTRY_LIST_T *) avc_calloc(1, sizeof(DIR_ENTRY_LIST_T)); } if(pEntryList) { pEntryList->cntTotal = cnt; pEntryList->cntTotalInDir = cntInDir; } //if(pEntryList) fprintf(stderr, "DIR '%s' num:%d numAlloc:%d pnext:0x%x TOTAL:%d/%d\n", dir, pEntryList->num, pEntryList->numAlloc, pEntryList->pnext, pEntryList->cntTotal, pEntryList->cntTotalInDir); return pEntryList; }
SYS_PROC_T *procdb_setup(SYS_PROCLIST_T *pProcs, const char *virtPath, const char *pId, const MEDIA_DESCRIPTION_T *pMediaDescr, const char *pXcodeStr, const char *pInstanceId, int lock) { SYS_PROC_T *pProc = NULL; if(!pProcs || !virtPath || virtPath[0] == '\0') { return NULL; } if(!(pProc = (SYS_PROC_T *) avc_calloc(1, sizeof(SYS_PROC_T)))) { return NULL; } strncpy(pProc->name, virtPath, SYS_PROC_NAME_MAX - 1); pProc->name[SYS_PROC_NAME_MAX - 1] = '\0'; if(pId) { strncpy(pProc->id, pId, META_FILE_IDSTR_MAX - 1); pProc->id[META_FILE_IDSTR_MAX - 1] = '\0'; } if(++pProcs->priorStartPort > pProcs->maxStartPort) { pProcs->priorStartPort = pProcs->minStartPort; } pProc->startPort = pProcs->priorStartPort; gettimeofday(&pProc->tmStart, NULL); memcpy(&pProc->tmLastAccess, &pProc->tmStart, sizeof(pProc->tmLastAccess)); memcpy(&pProc->tmLastPoll, &pProc->tmStart, sizeof(pProc->tmLastPoll)); memcpy(&pProc->tmLastPollActive, &pProc->tmStart, sizeof(pProc->tmLastPollActive)); pProc->flags = SYS_PROC_FLAG_PENDING; if(pMediaDescr) { memcpy(&pProc->mediaDescr, pMediaDescr, sizeof(pProc->mediaDescr)); if(pXcodeStr) { pProc->mbbps = procdb_getMbbps(pMediaDescr); } } if(pInstanceId && pInstanceId[0] != '\0') { strncpy(pProc->instanceId, pInstanceId, sizeof(pProc->instanceId)); } else { procdb_create_instanceId(pProc->instanceId); } // for the time being, each process uses 3 unique tcp ports pProcs->priorStartPort += MGR_PORT_ALLOC_COUNT; // // Add to list // if(lock) { pthread_mutex_lock(&pProcs->mtx); } if(pXcodeStr) { pProc->isXcoded = 1; pProcs->activeXcodeInstances++; } pProcs->activeInstances++; if(pProcs->procs) { pProc->pnext = pProcs->procs; } pProcs->procs = pProc; if(lock) { pthread_mutex_unlock(&pProcs->mtx); } return pProc; }
XCODE_IPC_DESCR_T *xcode_ipc_open(unsigned int sz, key_t key) { XCODE_IPC_DESCR_T *pIpc = NULL; struct shmid_ds buf; int shmid; //int rc; #ifdef __linux__ int flags = 0x180; #else int flags = SEM_R | SEM_A; #endif // __linux__ buf.shm_segsz = 0; if((shmid = shmget(key, 0, flags)) != -1) { // get the segment size of any existing shm if(shmctl(shmid, IPC_STAT, &buf) != 0) { return NULL; } } if(buf.shm_segsz == 0) { LOG(X_ERROR("xcode shared mem not yet created by writer")); return NULL; } if(buf.shm_segsz < sz) { LOG(X_ERROR("xcode shared mem size %d below minimum %d"), buf.shm_segsz, sz); return NULL; } pIpc = avc_calloc(1, sizeof(XCODE_IPC_DESCR_T)); pIpc->key = key; pIpc->sz = sz; if((pIpc->shmid = shmget(pIpc->key, pIpc->sz, flags)) == -1) { LOG(X_ERROR("xcode shmget failed for key: 0x%x flags: 0x%x size: %u"), pIpc->key, flags, pIpc->sz); free(pIpc); return NULL; } if(shmctl(pIpc->shmid, IPC_STAT, &buf) != 0) { LOG(X_ERROR("xcode shmctl failed for shmid %d"), pIpc->shmid); free(pIpc); return NULL; } if(buf.shm_nattch > 1) { LOG(X_ERROR("xcode shared mem already has %d attached"), buf.shm_nattch); free(pIpc); return NULL; } if((pIpc->pmem = shmat(pIpc->shmid, 0, 0)) == (void *) -1) { LOG(X_ERROR("xcode shmat failed")); free(pIpc); return NULL; } if((pIpc->sem_srv = sem_open(XCODE_IPC_SEM_NAME_SRV, 0, S_IRWXU | S_IRWXG | S_IRWXO , 0)) == SEM_FAILED) { LOG(X_ERROR("xcode sem_open server failed with "ERRNO_FMT_STR), ERRNO_FMT_ARGS); pIpc->sem_srv = NULL; return NULL; } if((pIpc->sem_cli = sem_open(XCODE_IPC_SEM_NAME_CLI, 0, S_IRWXU | S_IRWXG | S_IRWXO , 0)) == SEM_FAILED) { LOG(X_ERROR("xcode sem_open client failed with "ERRNO_FMT_STR), ERRNO_FMT_ARGS); pIpc->sem_cli = NULL; return NULL; } pIpc->pmem->hdr.cmd = XCODE_IPC_CMD_NONE; //fprintf(stderr, "init ipc ok\n"); return pIpc; }