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; }
int mediadb_mkdirfull(const char *root, const char *path) { size_t idxprev; struct stat st; size_t sz = 0; size_t len; char buf[VSX_MAX_PATH_LEN]; // fprintf(stdout, "mkdirfull '%s' '%s'\n", root, path); if(!path) { return -1; } if(root) { sz = strlen(root); } buf[sizeof(buf) - 1] = '\0'; idxprev = sz; len = strlen(path); for(; sz < len && sz < sizeof(buf); sz++) { if(path[sz] == DIR_DELIMETER) { memset(buf, 0, sizeof(buf)); strncpy(buf, path, sz); //fprintf(stdout, "stat '%s'\n", buf); if(strlen(buf) > 0 && fileops_stat(buf, &st) != 0) { LOG(X_DEBUG("Creating dir '%s'"), buf); if(fileops_MkDir(buf, S_IRWXU | S_IRWXG | S_IRWXO ) < 0) { LOG(X_ERROR("Unable to create dir '%s'"), buf); return -1; } } while(path[sz] == DIR_DELIMETER) { sz++; } idxprev = sz; //fprintf(stdout, "after'%s'\n", &path[sz]); } } if(sz > idxprev && fileops_stat(path, &st) != 0) { LOG(X_DEBUG("Creating dir '%s'"), path); if(fileops_MkDir(path, S_IRWXU | S_IRWXG | S_IRWXO ) < 0) { LOG(X_ERROR("Unable to create dir '%s'"), path); return -1; } } return 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; }
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; }
static int waitForFileContent(MP4_FILE_STREAM_T *pMp4Fs, unsigned int len) { //int rc = 0; struct stat st; FILE_STREAM_T *pFs = (FILE_STREAM_T *) pMp4Fs->pCbData; CAP_ASYNC_DESCR_T *pCapCfg = (CAP_ASYNC_DESCR_T *) pMp4Fs->pUserData; CAP_HTTP_MP4_T *pCapHttpMp4 = (CAP_HTTP_MP4_T *) pCapCfg->pUserData; struct timeval tv0, tv; unsigned int rcvTmtMs = pCapHttpMp4->mp4NetStream.rcvTmtMs; //fprintf(stderr, "WAIT FOR FILE C PUSERDATA: 0x%x\n", pCapCfg->pUserData); gettimeofday(&tv0, NULL); while(pFs->offset + len > pFs->size) { if(pCapCfg->running != 0 || g_proc_exit) { return -1; } // // Check the current file size to see if we have enough content to read // if(fileops_stat(pFs->filename, &st) != 0) { LOG(X_ERROR("Unable to get file size of '%s'."), pFs->filename); return -1; } else if(st.st_size != pFs->size) { pFs->size = st.st_size; pMp4Fs->size = pFs->size; } // // If the file does not have enough content to read, sleep and try again // if(pFs->offset + len > pFs->size) { //fprintf(stderr, "waitForFileContent... '%s', offset:%llu, len:%u, size:%llu, sleeping...\n", pFs->filename, pFs->offset, len, pFs->size); gettimeofday(&tv, NULL); if(TIME_TV_DIFF_MS(tv, tv0) > rcvTmtMs) { LOG(X_WARNING("Timeout %u ms exceeded when waiting for frame in '%s'"), rcvTmtMs, pMp4Fs->cbGetName(pMp4Fs)); pCapHttpMp4->rcvState.error = MP4_RCV_ERROR_RD_TMT; return -1; } usleep(10000); } } if(pCapCfg->running != 0 || g_proc_exit) { return -1; } return 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; }
int httplive_init(HTTPLIVE_DATA_T *pLive) { struct stat st; int rc = 0; if(!pLive) { return -1; } pLive->tvNextRoll.tv_sec = 0; pLive->tvPriorRoll.tv_sec = 0; if(pLive->duration <= 0) { pLive->duration = HTTPLIVE_DURATION_DEFAULT; } if(pLive->fs.fp != FILEOPS_INVALID_FP) { CloseMediaFile(&pLive->fs); } if(fileops_stat(pLive->dir, &st) != 0) { LOG(X_ERROR("HTTPLive dir '%s' does not exist."), pLive->dir); return -1; } if(pLive->fileprefix[0] == '\0') { strncpy(pLive->fileprefix, HTTPLIVE_TS_NAME_PRFX, sizeof(pLive->fileprefix)); } if(pLive->indexCount == 0) { pLive->indexCount = HTTPLIVE_NUM_INDEXES_M3U_DEFAULT; } else if(pLive->indexCount < HTTPLIVE_NUM_INDEXES_M3U_MIN) { pLive->indexCount = HTTPLIVE_NUM_INDEXES_M3U_MIN; } else if(pLive->indexCount > HTTPLIVE_NUM_INDEXES_M3U_MAX) { pLive->indexCount = HTTPLIVE_NUM_INDEXES_M3U_MAX; } httplive_delete(pLive); LOG(X_DEBUG("HTTPLive dir: '%s' duration: %.2fs file prefix: '%s'"), pLive->dir, pLive->duration, pLive->fileprefix); #if defined(HTTPLIVE_INCLUDE_PROGRAM_DATE_TIME) if(s_httplive_tm == 0) { s_httplive_tm = time(NULL); } #endif // HTTPLIVE_INCLUDE_PROGRAM_DATE_TIME return rc; }
int mpd_close(MPD_CREATE_CTXT_T *pCtxt, int deleteFiles, int dealloc) { int rc = 0; unsigned int idx; char mpdpath[VSX_MAX_PATH_LEN]; int outidx; struct stat st; if(!pCtxt) { return -1; } if(deleteFiles) { // // Remove playlist .mpd files // for(idx = 0; idx < sizeof(pCtxt->mpdOutputTypes) / sizeof(pCtxt->mpdOutputTypes[0]); idx++) { for(outidx = -1; outidx < IXCODE_VIDEO_OUT_MAX; outidx++) { write_mpd_path(pCtxt, outidx, pCtxt->mpdOutputTypes[idx].type, mpdpath, sizeof(mpdpath)); if(fileops_stat(mpdpath, &st) == 0 && (rc = fileops_DeleteFile(mpdpath)) != 0) { LOG(X_ERROR("Failed to delete '%s'"), mpdpath); } } } } if(dealloc) { for(idx = 0; idx < DASH_MPD_MAX_ADAPTATIONS; idx++) { if(pCtxt->segs[idx].pSegments) { avc_free((void **) &pCtxt->segs[idx].pSegments); } } } return rc; }
static int http_mp4_init(CAP_HTTP_MP4_T *pCapHttpMp4) { int rc = 0; struct stat st; if(pCapHttpMp4->rcvState.fStream.filename[0] == '\0') { return -1; } //if((codecfmt_init(&pCapHttpMp4->av, RTMP_TMPFRAME_VID_SZ, RTMP_TMPFRAME_AUD_SZ)) < 0) { // http_mp4_close(pCapHttpMp4); // return -1; //} if(!(pCapHttpMp4->pMp4FromNet = mp4net_open(pCapHttpMp4))) { http_mp4_close(pCapHttpMp4); return -1; } // // Delete any prior temporary mp4 file // if(fileops_stat(pCapHttpMp4->rcvState.fStream.filename, &st) == 0) { fileops_DeleteFile(pCapHttpMp4->rcvState.fStream.filename); } if((pCapHttpMp4->rcvState.fStream.fp = fileops_Open(pCapHttpMp4->rcvState.fStream.filename, O_RDWR | O_CREAT)) == FILEOPS_INVALID_FP) { LOG(X_ERROR("Unable to open %s for writing"), pCapHttpMp4->rcvState.fStream.filename); http_mp4_close(pCapHttpMp4); return -1; } pCapHttpMp4->rcvState.fStream.offset = 0; pCapHttpMp4->rcvState.fStream.size = 0; //fprintf(stderr, "VID PQ maxPkts:%d, maxPktLen:%d, grow:%d,%d\n", pCapHttpMp4->client.pQVid->cfg.maxPkts, pCapHttpMp4->client.pQVid->cfg.maxPktLen, pCapHttpMp4->client.pQVid->cfg.growMaxPkts, pCapHttpMp4->client.pQVid->cfg.growMaxPktLen); return rc; }
int metafile_isvalidFile(const char *path) { FILE_STREAM_T fs; int rc = 0; unsigned char buf[128]; struct stat st; size_t sz; size_t idx; int is_nl = 0; FILE_OFFSET_T fSize; if(!path) { return 0; } if(fileops_stat(path, &st) != 0 || (st.st_mode & S_IFDIR)) { return 0; } if(OpenMediaReadOnly(&fs, path) != 0) { return 0; } if((fSize = fs.size) > METAFILE_FILE_CHK_SZMAX) { fSize = METAFILE_FILE_CHK_SZMAX; } while(fs.offset < fSize && rc != 1) { sz = sizeof(buf); if(fs.offset + sz > fSize) { sz = (size_t) (fSize - fs.offset); } if(ReadFileStream(&fs, buf, sz) != sz) { break; } for(idx = 0; idx < sz; idx++) { if(!avc_istextchar(buf[idx])) { CloseMediaFile(&fs); return 0; } if(buf[idx] == '\n') { is_nl = 1; } else { if(is_nl) { if(!memcmp(&buf[idx], METAFILE_KEY_FILE, strlen(METAFILE_KEY_FILE)) || !memcmp(&buf[idx], METAFILE_KEY_DEVICE, strlen(METAFILE_KEY_DEVICE)) || !memcmp(&buf[idx], METAFILE_KEY_TITLE, strlen(METAFILE_KEY_TITLE)) || !memcmp(&buf[idx], METAFILE_KEY_DESCRIPTION, strlen(METAFILE_KEY_DESCRIPTION)) || !memcmp(&buf[idx], METAFILE_KEY_IGNORE, strlen(METAFILE_KEY_IGNORE)) || !memcmp(&buf[idx], METAFILE_KEY_RTMP_PROXY, strlen(METAFILE_KEY_RTMP_PROXY)) || !memcmp(&buf[idx], METAFILE_KEY_RTSP_PROXY, strlen(METAFILE_KEY_RTSP_PROXY)) || !memcmp(&buf[idx], METAFILE_KEY_HTTP_PROXY, strlen(METAFILE_KEY_HTTP_PROXY)) || !memcmp(&buf[idx], METAFILE_KEY_METHODS, strlen(METAFILE_KEY_METHODS)) || !memcmp(&buf[idx], METAFILE_KEY_TOKEN, strlen(METAFILE_KEY_TOKEN)) || !memcmp(&buf[idx], METAFILE_KEY_XCODEARGS, strlen(METAFILE_KEY_XCODEARGS))) { rc = 1; break; } } is_nl = 0; } } } CloseMediaFile(&fs); return rc; }
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); } }
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; }
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; }
static int update_fileentry(FILE_LIST_T *pFileList, const char *mediaName, const char *mediaPath, FILE_LIST_ENTRY_T **ppEntry) { MEDIA_DESCRIPTION_T mediaDescr; FILE_STREAM_T fileStream; FILE_LIST_ENTRY_T *pFileEntryCur = NULL; FILE_LIST_ENTRY_T *pFileEntryNew = NULL; FILE_LIST_ENTRY_T fileEntry; char buf[VSX_MAX_PATH_LEN]; struct stat st; struct stat st2; int havestat = 0; size_t szt; int fileChanged = 1; memset(&fileEntry, 0, sizeof(fileEntry)); //fprintf(stdout, "looking for '%s'\n", mediaName); if((pFileEntryCur = file_list_find(pFileList, mediaName))) { //fprintf(stdout, "found entry '%s' numTn:%d\n", pFileEntryCur->name, pFileEntryCur->numTn); // mark the entry as current to avoid deletion pFileEntryCur->flag = 1; if((havestat = !fileops_stat(mediaPath, &st)) == 0) { LOG(X_ERROR("Unable to stat '%s'"), mediaPath); } else if(st.st_size == pFileEntryCur->size && st.st_ctime == pFileEntryCur->tm) { fileChanged = 0; // // Special case to probe for recent creation .seek file // since the last time this entry was written // if(pFileEntryCur->duration == 0) { buf[sizeof(buf) - 1] = '\0'; strncpy(buf, mediaPath, sizeof(buf) - 1); if((szt = strlen(buf))) { strncpy(&buf[szt], MP2TS_FILE_SEEKIDX_NAME, sizeof(buf) - szt - 1); } if(fileops_stat(buf, &st2) == 0) { fileChanged = 1; } } } pFileEntryNew = pFileEntryCur; } else { // Check for invalid chars - ',' is used as a delimeter in .avcfidx if(strchr(mediaName, ',') || mediaName[0] == '#' || mediaName[0] == ' ' || mediaName[0] == '=') { LOG(X_WARNING("Illegal filename '%s' not added to database"), mediaPath); pFileEntryNew = NULL; fileChanged = 0; } else { LOG(X_DEBUG("Could not find database entry '%s'"), mediaPath); pFileEntryNew = &fileEntry; } } if(fileChanged) { if(OpenMediaReadOnly(&fileStream, mediaPath) == 0) { memset(&mediaDescr, 0, sizeof(mediaDescr)); if(filetype_getdescr(&fileStream, &mediaDescr, 1) == 0) { pFileEntryNew->flag = 1; pFileEntryNew->duration = mediaDescr.durationSec; pFileEntryNew->size = mediaDescr.totSz; if(!havestat && (havestat = !fileops_stat(mediaPath, &st)) == 0) { LOG(X_ERROR("Unable to stat new entry '%s'"), mediaPath); } if(havestat) { pFileEntryNew->tm = st.st_ctime; //fprintf(stderr, "-----------set tm:%ld %s\n", pFileEntryNew->tm, mediaPath); } if(mediaDescr.haveVid) { create_viddescrstr(&mediaDescr, pFileEntryNew->vstr, sizeof(pFileEntryNew->vstr)); } if(mediaDescr.haveAud) { create_auddescrstr(&mediaDescr, pFileEntryNew->astr, sizeof(pFileEntryNew->astr)); //fprintf(stdout, "aud descr:'%s'\n", pFileEntryNew->astr); } } else { pFileEntryNew->flag = 1; pFileEntryNew->size = fileStream.size; } CloseMediaFile(&fileStream); } // end of OpenMediaReadOnly if(pFileEntryCur == NULL) { pFileEntryNew->name[sizeof(pFileEntryNew->name) - 1] = '\0'; strncpy(pFileEntryNew->name, mediaName, sizeof(pFileEntryNew->name) - 1); pFileEntryCur = file_list_addcopy(pFileList, pFileEntryNew); } } // end of if(fileChanged) if(ppEntry) { *ppEntry = pFileEntryCur; } return fileChanged; }
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; }