示例#1
0
char *metafile_find(const char *pathmedia, 
                    char *pathbuf, 
                    unsigned int szpathbuf,
                    int *ploaddefault) {
  int sz;
  struct stat st;
  int loaddefault = 0;

  if(!pathmedia) {
  }

  if(ploaddefault) {
    loaddefault = *ploaddefault;
    *ploaddefault = 0;
  }

  VSX_DEBUG_METAFILE( LOG(X_DEBUG("META - metafile_find pathmedia: '%s', loaddefault: %d"), 
                         pathmedia, loaddefault));

  //
  // Check if the media resource is actually a meta file
  //
  if(metafile_isvalidFile(pathmedia)) {
    return (char *) pathmedia;
  }

  //
  // Try to load the metafile for the media resource
  //
  snprintf(pathbuf, szpathbuf, "%s%s", pathmedia, METAFILE_EXT);
  if(fileops_stat(pathbuf, &st) == 0) {
    return pathbuf; 
  }

  //
  // Try to load the directory wide metafile
  //
  if(loaddefault && (sz = mediadb_getdirlen(pathmedia)) > 0) {
    strncpy(pathbuf, pathmedia, szpathbuf);
    strncpy(&pathbuf[sz], METAFILE_DEFAULT, szpathbuf - sz);
    if(fileops_stat(pathbuf, &st) == 0) {
      if(ploaddefault) {
        *ploaddefault = 1;
      }
      return pathbuf;
    }
  }

  return NULL;
}
示例#2
0
static int check_filename(const char *filename, 
                          const char *path,
                          META_FILE_T *pMetaFile) {
  int sz;
  struct stat st;

  if(fileops_stat(filename, &st) != 0 && (sz = mediadb_getdirlen(path)) > 0) {
    strncpy(pMetaFile->filestr, path, sizeof(pMetaFile->filestr));
    strncpy(&pMetaFile->filestr[sz], filename, sizeof(pMetaFile->filestr) - sz);
  } else {
    strncpy(pMetaFile->filestr, filename, sizeof(pMetaFile->filestr));
  }

  return 0;
}
示例#3
0
static int createTn(const MEDIADB_DESCR_T *pMediaDb,
                    FILE_LIST_ENTRY_T *pFileListEntry, 
                    const char *pathMedia, const char *pathTn,
                    int numTn, int maxTnInIter) {
  int rc = 0;
  int highestTn = 0;
  struct stat st;
  unsigned int idx;
  char buf[VSX_MAX_PATH_LEN];
  char cmd[VSX_MAX_PATH_LEN];
  char cmdnice[64];
  char tmpfile[VSX_MAX_PATH_LEN];
  int numTnCreated = 0;
  char avcthumbsize[32];
  unsigned int secOffset;
  const char *avcthumb = pMediaDb->avcthumb;
  const char *avcthumblog = pMediaDb->avcthumblog;
  const char *avcthumb_file = avcthumb;
  const char *avcthumblog2 = avcthumblog;
#ifdef WIN32
  char curdir[VSX_MAX_PATH_LEN];
  char avcthumblogpath[VSX_MAX_PATH_LEN];
  char avcthumblogpath2[VSX_MAX_PATH_LEN];
  char avcthumblogprefix[64];
  size_t sz;
#endif // WIN32
#if defined(FFMPEG_THUMB_NEW)
  const char thumbsizedelim = ':';
#else // (FFMPEG_THUMB_NEW)
  const char thumbsizedelim = 'x';
#endif //  (FFMPEG_THUMB_NEW)

  tmpfile[0] = '\0';
  cmdnice[0] = '\0';

  //fprintf(stdout, "createTn '%s' numTn:%d, maxTnIter:%d, TN_MAX:%d, g_proc_exit:%d (0x%x)\n", pathTn, numTn, maxTnInIter, SRVMEDIA_TN_MAX, g_proc_exit, &g_proc_exit);

  for(idx = 0; idx < SRVMEDIA_TN_MAX; idx++) {

    if(idx > 0) {
      secOffset = (idx - 1) * SRVMEDIA_TN_INTERVAL_SEC;
    } else {
      secOffset = 4;
    }


    if(pFileListEntry->duration == 0) {

      snprintf(tmpfile, sizeof(tmpfile), "%s%s"VSXTMP_EXT, pathTn, pMediaDb->tn_suffix);
      if(fileops_stat(tmpfile, &st) != 0) {
 
        if(numTn == 0 && idx == 0) {
//fprintf(stdout, "creating tmp file '%s'\n", tmpfile);
          //
          // Create tmpfile which should only exist during 
          // creation of thumbnails for source of unknown duration
          // Since the "tn=" parameter in the index file denotes
          // the current number of thumbnails available
          //
          if(fileops_touchfile(tmpfile) != 0) {
            LOG(X_ERROR("Failed to create %s"), tmpfile);
          }
        } else if((int) idx >= numTn) {
//fprintf(stdout, "breaking out, have all the tns %d > %d\n", idx, numTn);
          break;
        }

      } else if(idx == SRVMEDIA_TN_MAX - 1) {
//fprintf(stdout, "removing tmp file '%s'\n", tmpfile);
        fileops_DeleteFile(tmpfile);
      }

    } else if(pFileListEntry->duration > 0 && secOffset >= pFileListEntry->duration - 1) {
      break;
    }

    if(idx == 0) {
      snprintf(avcthumbsize, sizeof(avcthumbsize), "%d%c%d", 
               pMediaDb->smTnWidth, thumbsizedelim, pMediaDb->smTnHeight);
      snprintf(buf, sizeof(buf), "%s%s.jpg", pathTn, pMediaDb->tn_suffix);    
    } else {
      snprintf(avcthumbsize, sizeof(avcthumbsize), "%d%c%d", 
               pMediaDb->lgTnWidth, thumbsizedelim, pMediaDb->lgTnHeight);
      snprintf(buf, sizeof(buf), "%s%s%u.jpg", pathTn, pMediaDb->tn_suffix, idx - 1);    
    }

    if(fileops_stat(buf, &st) < 0  || st.st_size == 0) {

#ifdef WIN32

      //
      // cd into directory of avcthumb script
      //
      avcthumblogprefix[0] = '\0';
      curdir[0] = '\0';
      fileops_getcwd(curdir, sizeof(curdir));
      if((sz = mediadb_getdirlen(avcthumb)) > 0) {
        if(sz >= sizeof(tmpfile)) {
          sz = sizeof(tmpfile) - 1;
        }
        tmpfile[sizeof(tmpfile) - 1] = '\0';
        strncpy(tmpfile, avcthumb, sizeof(tmpfile));
        if(sz > 0) {
          tmpfile[sz] = '\0';
          fileops_setcwd(tmpfile);
          avcthumb_file = &avcthumb[sz];
          snprintf(avcthumblogprefix, sizeof(avcthumblogprefix), "..\\");
        }
      }
      if(avcthumblog) {
        snprintf(avcthumblogpath, sizeof(avcthumblogpath), "%s%s", 
                 avcthumblogprefix, avcthumblog);
        snprintf(avcthumblogpath2, sizeof(avcthumblogpath2), "%s%s.err", 
                 avcthumblogprefix, avcthumblog);
        avcthumblog2 = avcthumblogpath2;
        avcthumblog = avcthumblogpath;
      }

#else

      snprintf(cmdnice, sizeof(cmdnice), "nice -n19 ");

#endif // WIN32
      

#if defined(FFMPEG_THUMB_NEW)
      //
      //TODO: create multiple thumbs on one run... will speed thnigs up alot!
      // '-ss 4 -vf "thumbnail,scale=164:90,fps=1/4" -frames:v 8'
      //
      snprintf(cmd, sizeof(cmd), "%s%s -v warning -i \"%s\" -an -vf \"thumbnail,scale=%s\" "
               "-frames:v 1 -f image2 -vcodec mjpeg -ss %u \"%s\" %s%s %s%s", 
               cmdnice,
               avcthumb_file, pathMedia, avcthumbsize, secOffset, buf, 
               avcthumblog ? ">>" : "", avcthumblog ? avcthumblog : "",
               avcthumblog2 ? "2>>" : "", avcthumblog2 ? avcthumblog2 : "");

#else // (FFMPEG_THUMB_NEW)
      snprintf(cmd, sizeof(cmd), "%s%s -i \"%s\" -an -s \"%s\" "
               "-vframes 1 -f image2 -vcodec mjpeg -ss %u \"%s\" %s%s %s%s", 
               cmdnice,
               avcthumb_file, pathMedia, avcthumbsize, secOffset, buf, 
               avcthumblog ? ">>" : "", avcthumblog ? avcthumblog : "",
               avcthumblog2 ? "2>>" : "", avcthumblog2 ? avcthumblog2 : "");
#endif // (FFMPEG_THUMB_NEW)
    
//if(numcmd++ > 2) {
//  return 0;
//}
      LOG(X_DEBUG("Creating thumbnail '%s'"), cmd);
      //TODO: seems that we're not getting SIGINT in the parent here... need a way to spawn (async?) & wait/poll
      rc = system(cmd);

#ifdef WIN32
      if(curdir[0] != '\0') {
        fileops_setcwd(curdir);
      }
#endif // WIN3

      //LOG(X_DEBUG("DOING STAT ON '%s'"), buf);
      if(fileops_stat(buf, &st) == 0  && st.st_size > 0) {
        rc = 0;
        highestTn = idx + 1;
        if(maxTnInIter > 0 && ++numTnCreated >= maxTnInIter) {
          break;
        }
      } else {
        rc = -1;
        LOG(X_WARNING("Failed to generate thumbnail '%s'"), buf);

        if(pFileListEntry->duration == 0) {
          snprintf(tmpfile, sizeof(tmpfile), "%s%s"VSXTMP_EXT, pathTn, pMediaDb->tn_suffix);    

          if(fileops_stat(tmpfile, &st) == 0) {
            fileops_DeleteFile(tmpfile);
          }
        } else {
          snprintf(tmpfile, sizeof(tmpfile), "%s%s."NOTN_EXT, pathTn, pMediaDb->tn_suffix);    
          if(fileops_touchfile(tmpfile) != 0) {
            LOG(X_ERROR("Failed to create %s"), tmpfile);
          }
        }

        if(idx == 0) {
          return -1;
        }
        break;
      }

    } else {
      highestTn = idx + 1;
    }

  }
  
  return highestTn;
}
示例#4
0
void mediadb_proc(void *parg) {
  MEDIADB_DESCR_T *pMediaDb = (MEDIADB_DESCR_T *) parg;
  struct stat st;
  char buf[VSX_MAX_PATH_LEN];
  const char *avcthumb = NULL;
  size_t sz;
  int rc;
  unsigned int iterIdx = 0;

  if(!pMediaDb->mediaDir) {
    return;
  }

  memset(buf, 0, sizeof(buf));
  sz = mediadb_getdirlen(pMediaDb->dbDir);
  strncpy(buf,  pMediaDb->dbDir, sizeof(buf) - 1);
  buf[sz] = '\0';

  LOG(X_DEBUG("Database dir: '%s'"), pMediaDb->dbDir);

  if(fileops_stat(buf, &st) != 0) {
    //
    // Create database root dir
    //
    LOG(X_DEBUG("Creating dir '%s'"), buf);
    if(fileops_MkDir(buf, S_IRWXU | S_IRWXG | S_IRWXO ) < 0) {
      LOG(X_CRITICAL("Unable to create database dir '%s'"), buf);
      return;
    }
  }

  if(fileops_stat(pMediaDb->dbDir, &st) != 0) {
    //
    // Create database subdir specific for mediaDir
    //
    LOG(X_DEBUG("Creating dir '%s'"), pMediaDb->dbDir);
    if(fileops_MkDir(pMediaDb->dbDir, S_IRWXU | S_IRWXG | S_IRWXO ) < 0) {
      LOG(X_CRITICAL("Unable to create database dir '%s'"), pMediaDb->dbDir);
      return;
    }
  }

  //
  // Check thumbnail creation script
  //
  if(pMediaDb->avcthumb) {

    if(fileops_stat(pMediaDb->avcthumb, &st) == 0) {

      //
      // Truncate the avcthumblog 
      //
      if(pMediaDb->avcthumblog) {
        snprintf(buf, sizeof(buf), DATE_CMD" > %s", pMediaDb->avcthumblog);
        //LOG(X_DEBUG("Executing system command '%s'"), buf);
        rc = system(buf);
        if(fileops_stat(pMediaDb->avcthumblog, &st) != 0) {
          pMediaDb->avcthumblog = NULL;
        }

      }

      if(pMediaDb->lgTnWidth == 0 || pMediaDb->lgTnWidth == 0) {
        pMediaDb->lgTnWidth = LG_THUMB_WIDTH;
        pMediaDb->lgTnHeight = LG_THUMB_HEIGHT;
      }
      if(pMediaDb->smTnWidth == 0 || pMediaDb->smTnHeight == 0) {
        pMediaDb->smTnWidth = SM_THUMB_WIDTH;
        pMediaDb->smTnHeight = SM_THUMB_HEIGHT;
      }

      LOG(X_DEBUG("Using %s to generate thumbnails %dx%d %dx%d"), 
                  pMediaDb->avcthumb,
                  pMediaDb->smTnWidth, pMediaDb->smTnHeight,
                  pMediaDb->lgTnWidth, pMediaDb->lgTnHeight);

    } else {

      LOG(X_WARNING("Unable to find %s  Video thumbnails disabled."), pMediaDb->avcthumb);
      pMediaDb->avcthumb = NULL;
    } 

  } else {
    LOG(X_WARNING("Not using video thumbnails.  Please set '%s=' in the configuration file."),
        SRV_CONF_KEY_AVCTHUMB);
  }

  //
  // Set avchumb to null and do not create thumbnails on first 
  // iteration to allow all avcfidx files to be created quickly
  //
  avcthumb = pMediaDb->avcthumb; 
  pMediaDb->avcthumb = NULL; 
  if(g_proc_exit == 0) {
    iterate_subdirs(pMediaDb, pMediaDb->dbDir, pMediaDb->mediaDir, 1, 0);
    pMediaDb->avcthumb = avcthumb; 
    usleep(2000000);
  }

  while(g_proc_exit == 0) {
    iterate_subdirs(pMediaDb, pMediaDb->dbDir, pMediaDb->mediaDir, 1, iterIdx++);
    usleep(10000000);
  }

}
示例#5
0
int http_gethttplive(CAP_ASYNC_DESCR_T *pCfg,
                         CAPTURE_CBDATA_T *pStreamsOut,
                         CAPTURE_STREAM_T *pStream,
                         const char *puri,
                         HTTP_RESP_T *pHttpResp,
                         HTTP_PARSE_CTXT_T *pHdrCtxt) {
  int rc = 0;
  char *path;
  const char *pbuf = pHdrCtxt->pbuf;
  unsigned int szbuf = pHdrCtxt->szbuf;
  const char *pm3ubuf;
  pthread_t ptd;
  pthread_attr_t attr;
  HTTPLIVE_CLIENT_T client;
  int highestIdx, lowestIdx, firstIdx;

  memset(&client, 0, sizeof(client));
  client.pCfg = pCfg;
  NETIOSOCK_FD(client.netsock) = INVALID_SOCKET;
  client.netsock.flags = pCfg->pSockList->netsockets[0].flags;
  client.pStreamsOut = pStreamsOut;
  client.pStream = pStream;
  client.running = -1;

  pthread_mutex_init(&client.mtx, NULL);

  do {

    //fprintf(stderr, "HTTP_GETHTTPLIVE sock: %d\n", NETIOSOCK_FD(pCfg->pSockList->netsockets[0]));

    if(NETIOSOCK_FD(pCfg->pSockList->netsockets[0]) == INVALID_SOCKET) {

//fprintf(stderr, "GOING TO CONNECT FOR M3U...\n");
      if((rc = httpcli_connect(&pCfg->pSockList->netsockets[0], &pCfg->pSockList->salist[0], 
                               "HTTPLive playlist thread")) < 0) {
        break;
      }

      memset(pHdrCtxt, 0, sizeof(HTTP_PARSE_CTXT_T));
      memset(pHttpResp, 0, sizeof(HTTP_RESP_T));
      pHdrCtxt->pnetsock = &pCfg->pSockList->netsockets[0];
      pHdrCtxt->pbuf = pbuf;
      pHdrCtxt->szbuf = szbuf;
      pHdrCtxt->tmtms = 0;
    }

    if((rc = mediadb_getdirlen(puri)) > 0) {
      if(rc >= sizeof(client.uriprefix)) {
        rc = sizeof(client.uriprefix) - 1;
      }
      memcpy(client.uriprefix, puri, rc);
    }

    if((pm3ubuf = get_m3u8(pCfg, puri, pHttpResp, pHdrCtxt, (unsigned char *) pbuf, 
                           szbuf))) {
      m3u_free(&client.pl, 0);
      memset(&client.pl, 0, sizeof(client.pl));

/*
pm3ubuf="#EXTM3U\r\n"
        "#EXT-X-VERSION:3\r\n"
        "#EXT-X-ALLOW-CACHE:NO\r\n"
        "#EXT-X-TARGETDURATION:14\r\n"
        "#EXT-X-MEDIA-SEQUENCE:2699\r\n"
        "#EXTINF:10,\r\n"
        "media_2699.ts?wowzasessionid=1144297750\r\n"
        "#EXTINF:10,\r\n"
        "media_2700.ts?wowzasessionid=1144297750\r\n"
        "#EXTINF:7,\r\n"
        "media_2701.ts?wowzasessionid=1144297750\r\n";
*/

      VSX_DEBUGLOG("Got m3u contents '%s'", pm3ubuf);
      //fprintf(stderr, "Got m3u contents '%s'\n", pm3ubuf);

      pthread_mutex_lock(&client.mtx);
      rc = m3u_create_buf(&client.pl, pm3ubuf);
      pthread_mutex_unlock(&client.mtx);

      if(rc > 0) {

        path = NULL;
        lowestIdx = find_lowest_idx(&client.pl, NULL);
        highestIdx = find_highest_idx(&client.pl, NULL);

        if(!client.insession) {

          if(highestIdx < 0) {
            LOG(X_WARNING("Unable to find httplive starting index from %s"), puri);
          } else {

            //
            // Some segmentors may write the last chunk to the playlist file even though
            // the chunk is still being appended on disk
            //
            //if(highestIdx > lowestIdx) {
            //  firstIdx = highestIdx - 1;
            //} else {
              firstIdx = highestIdx;
            //}

            client.curidx  = firstIdx;
            client.nextidx = client.curidx;
            client.insession = 1;

            pthread_attr_init(&attr);
            pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
            client.running = 1;

            if(pthread_create(&ptd, &attr, (void *) httplive_mediaproc, 
                              &client) != 0) {
              LOG(X_ERROR("Unable to create httplive media download thread"));
              rc = -1; 
              client.running = -1;
            }
          }

        } else { // client.insession

          //fprintf(stderr, "check playlist falling behind curidx:%d nextidx:%d, lowestIdx:%d, highestIdx:%d\n", client.curidx, client.nextidx, lowestIdx, highestIdx);
          //
          // Prevent falling behind playlist, a warning will be printed in the ts get thread
          //
          pthread_mutex_lock(&client.mtx);
          if(client.nextidx < lowestIdx) {
            client.nextidx = lowestIdx;
          }
          pthread_mutex_unlock(&client.mtx);
        }

        //if(rc >= 0) {
        //  m3u_dump(&client.pl);
        //}

      }

    } else { // get_m3u8
      rc = -1;
    }

    netio_closesocket(&pCfg->pSockList->netsockets[0]);

    if(rc >= 0) {
//fprintf(stderr, "M3U SLEEPING FOR %d\n", client.pl.targetDuration);
      if(client.pl.targetDuration > 0) {
        sleep(client.pl.targetDuration);
      } else {
        sleep(9);
      }
    }

  } while(rc >= 0);

  client.insession = 0;

  while(client.running != -1) {
    usleep(20000);
  } 

  m3u_free(&client.pl, 0);
  pthread_mutex_destroy(&client.mtx);

  return rc;
}