Пример #1
0
static int create_and_write_mpd(MPD_CREATE_CTXT_T *pCtxt, 
                                const MPD_ADAPTATION_T *pAdaptationList,
                                DASH_MPD_TYPE_T mpdType, 
                                int outidx,
                                int idxmax,
                                unsigned int mediaSequenceIndex,
                                int mediaSequenceMin) {
  int rc = 0;
  int idxbuf = 0;
  FILE_HANDLE fp;
  char buf[4096];
  char mpdpath[VSX_MAX_PATH_LEN];

  //
  // Create the .mpd xml file contents
  //
  if((idxbuf = mpd_doc_create(mpdType, pAdaptationList, pCtxt, 
                              outidx, mediaSequenceIndex, buf, sizeof(buf))) <= 0) {
    return -1;
  }

  //
  // Write the .mpd xml file to disk 
  //
  if((rc = write_mpd_path(pCtxt, outidx, mpdType, mpdpath, sizeof(mpdpath))) < 0) {
    return rc;
  }

  if((fp = fileops_Open(mpdpath, O_RDWR | O_CREAT)) == FILEOPS_INVALID_FP) {
    LOG(X_ERROR("Failed to open DASH mpd '%s' for writing"), mpdpath);
    return -1;
  }

  if((rc = fileops_WriteBinary(fp, (unsigned char *) buf, idxbuf)) < 0) {
    LOG(X_ERROR("Failed to write %d to DASH mpd '%s'"), idxbuf, mpdpath);
  }

  fileops_Close(fp);

  if(rc >= 0) {
    LOG(X_DEBUG("Updated DASH playlist '%s' (%d - %d)"), mpdpath, mediaSequenceMin, idxmax);
  } else {
    LOG(X_ERROR("Failed to update DASH playlist '%s' (%d - %d)"), mpdpath, mediaSequenceMin, idxmax);
  }

  return rc;
}
Пример #2
0
static int httplive_writepl_multibr(const char *path, const HTTPLIVE_DATA_T *pLiveArg) {
  FILE_HANDLE fp;
  int sz = 0;
  int rc = 0;
  char buf[4096];
  char tmp[32];
  int progId = 1;
  unsigned int bitrate;
  const char *uriprfxdelimeter = "";
  const HTTPLIVE_DATA_T *pLive = pLiveArg;

  if((rc = snprintf(&buf[sz], sizeof(buf) - sz, "#EXTM3U\r\n")) > 0) {
    sz += rc; 
  }

  while(pLive) {

    if((rc = snprintf(&buf[sz], sizeof(buf) - sz, 
                      "#%s:PROGRAM-ID=%d", HTTPLIVE_EXTX_STREAM_INFO, progId)) > 0) {
      sz += rc; 
    }

#define HTTPLIVE_BANDWIDTH(bw) (bw>1000 ? bw/1000*1000 : bw>100 ? bw/100*100 : bw>10 ? bw/10*10 : bw)

    bitrate = pLive->publishedBitrate ? pLive->publishedBitrate : pLive->autoBitrate;

    if(bitrate > 0) {
      if((rc = snprintf(&buf[sz], sizeof(buf) - sz, 
                      ", BANDWIDTH=%u", HTTPLIVE_BANDWIDTH(bitrate))) > 0) {
        sz += rc; 
      }
    }

    if((rc = snprintf(&buf[sz], sizeof(buf) - sz, "\r\n")) > 0) {
      sz += rc; 
    }

    if((rc = strlen(pLive->uriprefix)) > 0 && pLive->uriprefix[rc - 1] != '/') {
      uriprfxdelimeter = "/";
    } 

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

    if((rc = snprintf(&buf[sz], sizeof(buf) - sz, "%s%s%s%s%s\r\n",
          (pLive->uriprefix[0] != '\0' ? pLive->uriprefix : ""), 
          uriprfxdelimeter,
          tmp,
          //&pLive->fileprefix[pLive->outidx > 0 ? 1 : 0], HTTPLIVE_PL_NAME_EXT)) < 0) {
          HTTPLIVE_TS_NAME_PRFX, HTTPLIVE_PL_NAME_EXT)) < 0) {
      break;
    } else {
      sz += rc;
    }

    pLive = pLive->pnext;
  }

  if(rc >= 0) {

    if((fp = fileops_Open(path, O_RDWR | O_CREAT)) == FILEOPS_INVALID_FP) {
      LOG(X_ERROR("Failed to open '%s' for writing"), path);
      return -1;
    }

    if((rc = fileops_WriteBinary(fp, (unsigned char *) buf, sz)) < 0) {
      LOG(X_ERROR("Failed to write %d to '%s'"), sz, path);
    }

    fileops_Close(fp);

  }

  if(rc >= 0) {
    LOG(X_DEBUG("Updated master playlist '%s'"), path);
  } else {
    LOG(X_ERROR("Failed to update master playlist '%s'"), path);
  }

  return rc;
}
Пример #3
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;
}
Пример #4
0
static int httplive_writepl(const char *path, int idxmin, int idxmax, HTTPLIVE_DATA_T *pLive) {
  FILE_HANDLE fp;
  int idx;
  int sz = 0;
  int rc = 0;
  char filename[128];
  char buf[4096];
  const char *uriprfxdelimeter = "";
  unsigned int duration = (unsigned int) pLive->duration;
  
  if(pLive->duration > (float) duration) {
    duration++;
  }

  if((rc = snprintf(buf, sizeof(buf), 
                "#EXTM3U\r\n#%s:%d\r\n#%s:%d\r\n",
                HTTPLIVE_EXTX_TARGET_DURATION, duration,
                HTTPLIVE_EXTX_MEDIA_SEQUENCE, idxmin)) > 0) {
    sz += rc; 

    if(rc >= 0 && (rc = snprintf(&buf[sz], sizeof(buf) - sz, "#EXT-X-ALLOW-CACHE:NO\r\n")) > 0) {
      sz += rc;
    }

#if defined(HTTPLIVE_INCLUDE_PROGRAM_DATE_TIME)
    char tmbuf[256];
    time_t tm = s_httplive_tm + (pLive->curIdx * duration);
    strftime(tmbuf, sizeof(tmbuf) - 1, "%Y-%m-%dT%H:%M:%S+08:00", gmtime(&tm));
    //fprintf(stderr, "TM:%u, %u, %d * %d '%s'\n", tm, s_httplive_tm, pLive->curIdx, duration, tmbuf);
    if(rc >= 0 && (rc = snprintf(&buf[sz], sizeof(buf) - sz, "#EXT-X-PROGRAM-DATE-TIME:%s\r\n", tmbuf)) > 0) {
      sz += rc;
    }
#endif // HTTPLIVE_INCLUDE_PROGRAM_DATE_TIME

    if(pLive->uriprefix && (rc = strlen(pLive->uriprefix)) > 0 && pLive->uriprefix[rc - 1] != '/') {
      uriprfxdelimeter = "/";
    } 

    for(idx = idxmin; idx <= idxmax; idx++) {

      httplive_format_path(filename, sizeof(filename), pLive->fileprefix, idx);

      if((rc = snprintf(&buf[sz], sizeof(buf) - sz, "#EXTINF:%d,\r\n%s%s%s\r\n"
          ,duration, 
          (pLive->uriprefix ? pLive->uriprefix : ""), 
          uriprfxdelimeter, filename)) < 0) {
        break;
      } else {
        sz += rc;
      }
    }

  }

  //
  // For live streams, do not end with #EXT-X-ENDLIST
  //

  if(rc >= 0) {

    if((fp = fileops_Open(path, O_RDWR | O_CREAT)) == FILEOPS_INVALID_FP) {
      LOG(X_ERROR("Failed to open httplive playlist '%s' for writing"), path);
      return -1;
    }

    if((rc = fileops_WriteBinary(fp, (unsigned char *) buf, sz)) < 0) {
      LOG(X_ERROR("Failed to write %d to httplive playlist '%s'"), sz, path);
    }

    fileops_Close(fp);

  }

  if(rc >= 0) {
    LOG(X_DEBUG("Updated httplive playlist '%s' (%d - %d)"), path, idxmin, idxmax);
  } else {
    LOG(X_ERROR("Failed to update httplive playlist '%s' (%d - %d)"), path, idxmin, idxmax);
  }

  return rc;
}