Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
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;
}
Example #6
0
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;
}
Example #7
0
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;

}
Example #8
0
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;
}
Example #9
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;
}
Example #10
0
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;
}
Example #11
0
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;
}
Example #12
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;
}
Example #13
0
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;
}
Example #14
0
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;
}
Example #15
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;
}
Example #16
0
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;
}
Example #17
0
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;
}
Example #18
0
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;
} 
Example #19
0
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;
}
Example #20
0
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;
}
Example #21
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;
}
Example #22
0
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;
}
Example #23
0
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;
}