예제 #1
0
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;
}
예제 #2
0
int mediadb_prepend_dir2(const char *dir1, const char *dir2, const char *path,
                         char *out, unsigned int lenout) {
  int rc;
  char tmp[VSX_MAX_PATH_LEN];
  
  if((rc = mediadb_prepend_dir(dir1, dir2, tmp, sizeof(tmp)) >= 0)) {
     rc = mediadb_prepend_dir(tmp, path, out, lenout);
  }

  return rc;
}
예제 #3
0
파일: mpd.c 프로젝트: amirsdream/openvcx
static float getMediaRateBps(const MPD_CREATE_CTXT_T *pCtxt, 
                             unsigned int outidx, 
                             const MPD_ADAPTATION_T *pAdaptation) {
  FILE_OFFSET_T size = 0;
  struct stat st;
  float durationSec = 0;
  float rateBps = 0;
  char tmp[256];
  char mediaPath[VSX_MAX_PATH_LEN];

  mpd_format_path(tmp, sizeof(tmp), mpd_format_path_prefix, outidx,
                    pCtxt->init.outfileprefix, pAdaptation->pMedia->mediaUniqIdstr, pCtxt->init.outfilesuffix,
                    pAdaptation->padaptationTag);
  mediadb_prepend_dir(pAdaptation->pMedia->mediaDir, tmp, mediaPath, sizeof(mediaPath));

 if(mediaPath[0] != '\0' && fileops_stat(mediaPath, &st) == 0) {
    size = (FILE_OFFSET_T) st.st_size;
  }

  //LOG(X_DEBUG("GETMEDIARATEBPS mediaPath: '%s', size: %lld"), mediaPath, size);

  if(pAdaptation->pMedia->timescale > 0) {
    durationSec = (float) ((double) pAdaptation->pMedia->duration / pAdaptation->pMedia->timescale);
  }

  if(durationSec > 0) {
    rateBps = 8 * size / durationSec;
  }

  return rateBps;
}
예제 #4
0
static int httplive_updatepl(HTTPLIVE_DATA_T *pLive) {
  int rc = 0;
  unsigned int idxMin;
  char filename[64];
  char path[VSX_MAX_PATH_LEN];

  if(pLive->curIdx <= 0) {
    return 0;
  }

  if(pLive->curIdx <= pLive->indexCount) {
    idxMin = 0;
  } else {
    idxMin = pLive->curIdx - pLive->indexCount;
  }

  snprintf(filename, sizeof(filename), "%s"HTTPLIVE_PL_NAME_EXT, pLive->fileprefix);
  mediadb_prepend_dir(pLive->dir, filename, path, sizeof(path));

  rc = httplive_writepl(path, idxMin, pLive->curIdx - 1, pLive);

  //
  // Write the master playlist containing bitrate specific playlists
  // only when multi xcode output is set
  //
  if(pLive->curIdx == 1 && pLive->outidx == 0) {

    update_multibr(pLive);
    if(pLive->count > 1) {
      snprintf(filename, sizeof(filename), "%s"HTTPLIVE_PL_NAME_EXT, HTTPLIVE_MULTIBITRATE_NAME_PRFX);
      mediadb_prepend_dir(pLive->dir, filename, path, sizeof(path));
      httplive_writepl_multibr(path, pLive);
    }
  }

  return rc;
}
예제 #5
0
static int clearTn(const char *pathMedia, const char *pathDb, 
                   const FILE_LIST_T *pFileList) {

  DIR *pdir;
  struct dirent *direntry;
  char buf[VSX_MAX_PATH_LEN];
  char buf2[VSX_MAX_PATH_LEN];
  size_t sz,sz2;

  if(!(pdir = fileops_OpenDir(pathDb))) {
    return -1;
  }

  buf[sizeof(buf) - 1] = '\0';

  while((direntry = fileops_ReadDir(pdir))) {
    if(!(direntry->d_type & DT_DIR)) {

      // "_tn[idx].jpg"
      if((sz = strlen(direntry->d_name)) > 9 && 
         (!strncasecmp(&direntry->d_name[sz - 4], ".jpg", 4) ||
       !strncasecmp(&direntry->d_name[sz - VSXTMP_EXT_LEN], VSXTMP_EXT, VSXTMP_EXT_LEN) ||
         !strncasecmp(&direntry->d_name[sz - NOTN_EXT_LEN], NOTN_EXT, NOTN_EXT_LEN))) {

        strncpy(buf, direntry->d_name, sizeof(buf) - 1);
        for(sz2 = sz - 4; sz2 > sz - 12; sz2--) { 
          if(buf[sz2] == '_') {
            break;
          }
        }
        buf[sz2] = '\0';
//fprintf(stdout, "check '%s' '%s'\n", buf, direntry->d_name);

        if(file_list_find(pFileList, buf) == NULL) {
          mediadb_prepend_dir(pathDb, direntry->d_name, buf2, sizeof(buf));  
          LOG(X_DEBUG("Removing thumbnail '%s'\n"), buf2);
          if(fileops_DeleteFile(buf2) != 0) {
            LOG(X_ERROR("Failed to delete thumbnail %s"), buf2);
          }
        }

      }
    }
  }

  fileops_CloseDir(pdir);

  return 0;
}
예제 #6
0
파일: mpd.c 프로젝트: amirsdream/openvcx
static int write_mpd_path(const MPD_CREATE_CTXT_T *pCtxt, 
                          int outidx, 
                          DASH_MPD_TYPE_T mpdType,
                          char *buf, 
                          unsigned int szbuf) {

  int rc = 0;
  char stroutidx[32];
  char mpdfilename[VSX_MAX_PATH_LEN];

  if(outidx >= 0) {
    snprintf(stroutidx, sizeof(stroutidx), "%d", outidx + 1);
  } else {
    stroutidx[0] = '\0';
  }

  snprintf(mpdfilename, sizeof(mpdfilename), "%s%s", stroutidx, mpd_type_to_filename(mpdType));

  mediadb_prepend_dir(pCtxt->init.outdir, mpdfilename, buf, szbuf);

  return rc;
}
예제 #7
0
static int iterate_subdirs(const MEDIADB_DESCR_T *pMediaDb, const char *pathDb, 
                           const char *pathMedia, int level, unsigned int iterIdx) {
  DIR *pdir;
  FILE_LIST_T fileList;
  FILE_LIST_ENTRY_T *pFileListEntry;
  struct dirent *direntry;
  char bufMedia[VSX_MAX_PATH_LEN];
  char bufDb[VSX_MAX_PATH_LEN];
  char tmpfile[VSX_MAX_PATH_LEN];
  int rc = 0;
  int rcsub = 0;
  int fileListChanged = 0;
  int numTnCreated = 0;
  int highestTn;
  struct stat st;

//fprintf(stdout, "%d dir:'%s' '%s'\n", level, pathDb, pathMedia);

  //
  // TODO: escape invalid chars in pathnames ' , & # $ '
  // 

  if(level >= SRVMEDIA_MAX_LEVELS) {
    LOG(X_WARNING("Path '%s' exceeded max number of subdirs under %s"), 
        pathMedia, pMediaDb->mediaDir);
    return -1;
  }

  if(!(pdir = fileops_OpenDir(pathMedia))) {
    return -1;
  }

  memset(&fileList, 0, sizeof(fileList));
  file_list_read(pathDb, &fileList);
  strncpy(fileList.pathmedia, pathMedia, sizeof(fileList.pathmedia) - 1);


  while((direntry = fileops_ReadDir(pdir)) && g_proc_exit == 0) {
//fprintf(stdout, "- %d %s\n", level, direntry->d_name);
    if(direntry->d_type & DT_DIR) {

      if(mediadb_isvalidDirName(pMediaDb, direntry->d_name)) {

        if(mediadb_prepend_dir(pathDb, direntry->d_name, bufDb, sizeof(bufDb)) < 0) {
          LOG(X_WARNING("Unable to concatenate subdir %s %s"), bufDb, direntry->d_name);
        } else if(mediadb_prepend_dir(pathMedia, direntry->d_name, bufMedia, sizeof(bufMedia)) < 0) {
          LOG(X_WARNING("Unable to concatenate subdir %s %s"), bufMedia, direntry->d_name);
        } else {

          if(numTnCreated > 1) {
            file_list_write(pathDb, &fileList);
          }

          if((rcsub = iterate_subdirs(pMediaDb, bufDb, bufMedia, 
                                      level+1, iterIdx)) < 0) {
            rc = rcsub;
          }
          if(g_proc_exit != 0) {
            break;
          }

        }

      } else if(direntry->d_name[0] != '.') {
        //fprintf(stderr, "skipping directory '%s'\n", direntry->d_name);
      }

    } else if(mediadb_isvalidFileName(pMediaDb, direntry->d_name, 1, 0)) {

//fprintf(stdout, "%d media file %s '%s'\n", level, pathMedia, direntry->d_name);

      if(fileops_stat(pathDb, &st) != 0 && mediadb_mkdirfull(pMediaDb->dbDir, pathDb) < 0) {
        continue;
      } 

      if(mediadb_prepend_dir(pathDb, direntry->d_name, bufDb, sizeof(bufDb)) < 0) {
        LOG(X_ERROR("Unable to concatenate subdir %s %s"), bufDb, direntry->d_name);
        continue;
      } else if(mediadb_prepend_dir(pathMedia, direntry->d_name, bufMedia, sizeof(bufMedia)) < 0) {
        LOG(X_ERROR("Unable to concatenate subdir %s %s"), bufMedia, direntry->d_name);
        continue;
      }

      if(update_fileentry(&fileList, direntry->d_name, bufMedia, &pFileListEntry) > 0) {

        LOG(X_DEBUG("'%s' changed ('%s')"), direntry->d_name, pFileListEntry->name);

        fileListChanged = 1;
        if(pFileListEntry->numTn < 0) {
          pFileListEntry->numTn = 0;
        }

      }

      if(pMediaDb->avcthumb && pFileListEntry && pFileListEntry->vstr[0] != '\0' &&
         pFileListEntry->numTn != -1) {

        //
        // On very first iteration, check all thumbnails
        //
        snprintf(tmpfile, sizeof(tmpfile), "%s%s."NOTN_EXT, bufDb, pMediaDb->tn_suffix);

        if(fileops_stat(tmpfile, &st) == 0 && iterIdx > 0) {
          //  
          // Ignore thumbnail creation if the .notn file has been
          // previously created on an error condition
          //

        } else 
        //
        // Update thumbnail info
        //
        if((highestTn = createTn(pMediaDb, pFileListEntry, bufMedia, bufDb, 
            pFileListEntry->numTn, 1)) > pFileListEntry->numTn || highestTn == -1) {

          pFileListEntry->numTn = highestTn;
          fileListChanged = 1;

          // Periodically update the db file
          if(numTnCreated > 10) {
            file_list_write(pathDb, &fileList);
            numTnCreated = 0;
          }

        }

      }

    } else {
//fprintf(stdout, "skipping %s '%s'\n", pathMedia, direntry->d_name);
    }

  }

  fileops_CloseDir(pdir);

  if(g_proc_exit == 0) {

    if(file_list_removeunmarked(&fileList) || fileListChanged) {

       LOG(X_DEBUG("Writing file index in %s"), pathDb);
//fprintf(stdout, "level:%u\n", level);
      file_list_write(pathDb, &fileList);
    }

    //
    //Remove thumbnails which are not included in the fileList
    //
    clearTn(pathMedia, pathDb, &fileList);
  }

  file_list_close(&fileList);

  return rc;
}
예제 #8
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;
}
예제 #9
0
int http_purge_segments(const char *dirpath, 
                        const char *fileprefix, 
                        const char *ext, 
                        unsigned int idxmin, 
                        int purgeNonIdx) {

  DIR *pdir;
  struct dirent *direntry;
  //struct stat st;
  char path[VSX_MAX_PATH_LEN];
  int rc = 0;
  char stridx[32];
  unsigned int idx;
  size_t sz;
  size_t szext;
  unsigned int szprfx;
  int isNumeric;

  if(!dirpath || !fileprefix || !ext) {
    return -1;
  }

  //fprintf(stderr, "http_purge_segments '%s', '%s', '%s', idxmin:%d\n", dirpath, fileprefix, ext, idxmin); 

  if(!(pdir = fileops_OpenDir(dirpath))) {
    return -1;
  } 

  szprfx = strlen(fileprefix);
  szext = strlen(ext);

  while((direntry = fileops_ReadDir(pdir))) {

    if(!(direntry->d_type & DT_DIR) &&
       (sz = strlen(direntry->d_name)) >= 7 &&
       !strncasecmp(&direntry->d_name[sz - szext], ext, szext) &&
       !strncasecmp(direntry->d_name, fileprefix, szprfx)) {

      if((sz = (sz - szprfx - szext)) >= sizeof(stridx)) {
        sz = sizeof(stridx) - 1;
      }
      memcpy(stridx, &direntry->d_name[szprfx], sz);
      stridx[sz] = '\0';
      isNumeric = 1;
      for(idx = 0; idx < sz; idx++) {
        if(!CHAR_NUMERIC(stridx[idx])) {
          isNumeric = 0;
          break;
        }
      }    

      if(isNumeric) {
        idx = atoi(stridx);
      } else if(purgeNonIdx) {
        idx = 0;
      } else {
        idx = idxmin;
      }
  
      //fprintf(stderr, "purge_segment '%s' idx:%d ('%s') < %d\n", direntry->d_name, idx, stridx, idxmin);

      if(idx < idxmin) {

        mediadb_prepend_dir(dirpath, direntry->d_name, path, sizeof(path));

        LOG(X_DEBUG("Deleting '%s'"), path);
        if(fileops_DeleteFile(path) != 0) {
          LOG(X_ERROR("Failed to delete '%s'"), path);
        }
      }
    
    }
  }
 
  fileops_CloseDir(pdir);

  return rc;
}
예제 #10
0
int httplive_cbOnPkt(void *pUserData, const unsigned char *pPktData, unsigned int len) {
  int rc = 0, rc2;
  struct timeval tv;
  char filename[VSX_MAX_PATH_LEN];
  unsigned int idxMin = 0;
  int keepIdx;
  HTTPLIVE_DATA_T *pLive = (HTTPLIVE_DATA_T *) pUserData;

  if(!pLive || !pPktData) {
    return -1;
  }

  //fprintf(stderr, "httplive_cbOnPkt len:%d, outidx[%d]\n", len, pLive->outidx);

  if(len == 0) {
    LOG(X_WARNING("httplive cb called with 0 length"));
    return 0;  
  }

  gettimeofday(&tv, NULL);

  if(pLive->tvNextRoll.tv_sec == 0 ||
     TIME_TV_DIFF_MS(tv, pLive->tvNextRoll) >= (long) (pLive->duration * 1000.0f)) {

    if(pLive->fs.fp != FILEOPS_INVALID_FP) {
      //LOG(X_DEBUG("HTTPLIVE CLOSING fp:0x%x, fileno:%d %s"), pLive->fs.fp, pLive->fs.fp ? fileno(pLive->fs.fp) : -99, pLive->fs.filename);
      closeFp(pLive);
      //LOG(X_DEBUG("HTTPLIVE CLOSED fp:0x%x, fileno:%d %s"), pLive->fs.fp, pLive->fs.fp ? fileno(pLive->fs.fp) : -99, pLive->fs.filename);
    }

    keepIdx = HTTPLIVE_NUM_INDEXES_KEEP(pLive);

    if(pLive->curIdx > keepIdx + 2) {
      idxMin = pLive->curIdx - keepIdx - 2;
      httplive_purgetsfiles(pLive, idxMin);
    }

    //
    // Update MPEG-DASH playlist using .ts segments
    //
    if(pLive->pMpdMp2tsCtxt && pLive->curIdx > 0) {
      on_new_ts(pLive->curIdx-1, idxMin, pLive->outidx, 
                pLive->dir, pLive->curIdx,
               //pLive->fs.filename, 
                pLive->pMpdMp2tsCtxt, 90000, (pLive->duration * 90000), 
                TIME_TV_DIFF_MS(pLive->tvPriorRoll, pLive->tvRoll0) * 90);
    }

    httplive_format_path(filename, sizeof(filename), pLive->fileprefix, pLive->curIdx);
    mediadb_prepend_dir(pLive->dir, filename, pLive->fs.filename, sizeof(pLive->fs.filename));

    if((pLive->fs.fp = fileops_Open(pLive->fs.filename, O_RDWR | O_CREAT)) == FILEOPS_INVALID_FP) {
      LOG(X_ERROR("Failed to open '%s' for writing"), pLive->fs.filename);
      rc = -1;    
    } else {

      LOG(X_DEBUG("Opened '%s'"), pLive->fs.filename);

      rc = httplive_updatepl(pLive);

    }

    pLive->curIdx++;
    if(pLive->tvNextRoll.tv_sec == 0) {
      TIME_TV_SET(pLive->tvNextRoll, tv);
      TIME_TV_SET(pLive->tvRoll0, tv);
    }
    //fprintf(stderr, "TV  at %u:%u\n", tv.tv_sec, tv.tv_usec);
    
    TIME_TV_SET(pLive->tvPriorRoll, pLive->tvNextRoll);
    TV_INCREMENT_MS(pLive->tvNextRoll, (pLive->duration * 1000.0f));
    //fprintf(stderr, "TV next at %u:%u, msElapsed:%u, idxMin:%d, curIdx:%d\n", pLive->tvNextRoll.tv_sec, pLive->tvNextRoll.tv_usec, TIME_TV_DIFF_MS(pLive->tvNextRoll, pLive->tvRoll0), idxMin, pLive->curIdx);

  }

  //LOG(X_DEBUG("HTTPLIVE WRITE  %d fp:0x%x, pPktData:0x%x, fileno:%d %s"), len, pLive->fs.fp, pPktData, pLive->fs.fp ? fileno(pLive->fs.fp) : -99, pLive->fs.filename);
  if(pLive->fs.fp != FILEOPS_INVALID_FP &&
     (rc2 = fileops_WriteBinary(pLive->fs.fp, (unsigned char *) pPktData, len)) != len) {
    LOG(X_ERROR("Failed to write %d/%d to output ts %s"), rc2, len, pLive->fs.filename);

    //LOG(X_DEBUG("HTTPLIVE WRITE ERROR %d, %d fp:0x%x, pPktData:0x%x, fileno:%d %s"), rc2, len, pLive->fs.fp, pPktData, pLive->fs.fp ? fileno(pLive->fs.fp) : -99, pLive->fs.filename);
    return -1;
  }


  return rc;
}