61static void init_stat(
struct stat *stbuf,
size_t fsize, time_t ftime,
bool directory);
65static bool virtual_name(std::string *virtualpath,
const std::string &origpath =
"",
const FFmpegfs_Format **current_format =
nullptr);
74static std::string
get_number(
const char *path, uint32_t *value);
78static int selector(
const struct dirent * de);
79static int scandir(
const char *dirp, std::vector<struct dirent> * _namelist,
int (*
selector) (
const struct dirent *),
int (*cmp) (
const struct dirent **,
const struct dirent **));
82static int ffmpegfs_readdir(
const char *path,
void *buf, fuse_fill_dir_t filler, off_t offset,
struct fuse_file_info *fi,
enum fuse_readdir_flags flags);
83static int ffmpegfs_getattr(
const char *path,
struct stat *stbuf, fuse_file_info *fi);
85static int ffmpegfs_open(
const char *path,
struct fuse_file_info *fi);
86static int ffmpegfs_read(
const char *path,
char *buf,
size_t size, off_t offset,
struct fuse_file_info *fi);
89static void *
ffmpegfs_init(
struct fuse_conn_info *conn, fuse_config *cfg);
102std::unique_ptr<thread_pool>
tp;
115 static const std::set<std::string, comp> passthrough_set =
244 return (passthrough_set.find(ext) != passthrough_set.cend());
271 std::string origpath;
272 std::string transcoded;
280 len = readlink(origpath.c_str(), buf, size - 2);
289 strncat(buf, transcoded.c_str(), size);
307static int ffmpegfs_readdir(
const char *path,
void *buf, fuse_fill_dir_t filler, off_t offset,
struct fuse_file_info *fi,
enum fuse_readdir_flags flags)
312 std::string origpath;
328 if (virtualfile ==
nullptr)
330#if defined(USE_LIBBLURAY) || defined(USE_LIBDVD) || defined(USE_LIBVCD)
339 return (res >= 0 ? 0 : res);
347 return (res >= 0 ? 0 : res);
355 return (res >= 0 ? 0 : res);
362 DIR *dp = opendir(origpath.c_str());
367 std::map<const std::string, struct stat> files;
370 for (
struct dirent *de = readdir(dp); de !=
nullptr; de = readdir(dp))
374 if (lstat((origpath + de->d_name).c_str(), &stbuf) == -1)
380 files.insert({ de->d_name, stbuf });
384 for (
auto& [key, value] : files)
386 std::string origname(key);
393 std::string origfile;
394 std::string filename(key);
395 struct stat & stbuf = value;
398 origfile = origpath + origname;
403 if (S_ISREG(stbuf.st_mode) || S_ISLNK(stbuf.st_mode))
410 if (current_format->
video_codec() == AV_CODEC_ID_NONE)
414 if (newvirtualfile ==
nullptr)
417 Logging::error(origfile,
"INTERNAL ERROR: ffmpegfs_readdir()! newvirtualfile is NULL.");
426 Logging::debug(origfile,
"Unable to transcode. The source has no audio stream, but the target just supports audio.");
517 else if (ffmpegfs_format->
is_hls())
528 load_path(origpath,
nullptr, buf, filler);
558 std::string origpath;
572 if (virtualfile ==
nullptr && lstat(origpath.c_str(), stbuf) == 0)
576 std::string filename(origpath);
578 if (S_ISREG(stbuf->st_mode) &&
virtual_name(&filename,
"", ¤t_format))
589 Logging::trace(origpath,
"getattr: Creating frame set directory of file.");
597 else if (current_format->
is_hls())
606 Logging::trace(origpath,
"getattr: Treating existing file/directory as passthrough.");
614 Logging::debug(origpath,
"getattr: File not recoded because --recodesame=NO.");
625 bool no_check =
false;
632 mempcpy(stbuf, &virtualfile->
m_st,
sizeof(
struct stat));
647 mempcpy(stbuf, &virtualfile->
m_st,
sizeof(
struct stat));
655 mempcpy(stbuf, &virtualfile->
m_st,
sizeof(
struct stat));
663 if (!no_check && lstat(origpath.c_str(), stbuf) == -1)
670 if (virtualfile ==
nullptr)
672 std::string pathonly(origpath);
702 std::string origfile(origpath);
738 if (virtualfile2 ==
nullptr)
744 mempcpy(stbuf, &virtualfile2->
m_st,
sizeof(
struct stat));
770 if (virtualfile2 ==
nullptr)
776 mempcpy(stbuf, &virtualfile2->
m_st,
sizeof(
struct stat));
788 return (!res ? error : res);
794 if (virtualfile ==
nullptr)
800 mempcpy(stbuf, &virtualfile->
m_st,
sizeof(
struct stat));
815 else if (S_ISREG(stbuf->st_mode))
818 if (virtualfile ==
nullptr)
827 if (cache_entry ==
nullptr)
843 mempcpy(stbuf, &virtualfile->
m_st,
sizeof(
struct stat));
979 std::string origpath;
989 int fd = open(origpath.c_str(), fi->flags);
1013 switch (virtualfile->
m_type)
1035 if (parent_file !=
nullptr)
1045 if (cache_entry ==
nullptr)
1051 fi->fh =
reinterpret_cast<uintptr_t
>(cache_entry);
1065 if (cache_entry ==
nullptr)
1071 fi->fh =
reinterpret_cast<uintptr_t
>(cache_entry);
1101static int ffmpegfs_read(
const char *path,
char *buf,
size_t size, off_t offset,
struct fuse_file_info *fi)
1103 std::string origpath;
1104 size_t locoffset =
static_cast<size_t>(offset);
1107 Logging::trace(path,
"read: Reading %1 bytes from offset %2 to %3.", size, locoffset, size + locoffset);
1115 int fd = open(origpath.c_str(), O_RDONLY);
1119 bytes_read =
static_cast<int>(pread(fd, buf, size, offset));
1121 if (bytes_read >= 0)
1130 else if (errno != ENOENT)
1143 bool success =
true;
1145 if (virtualfile ==
nullptr)
1148 Logging::error(origpath.c_str(),
"read: INTERNAL ERROR: ffmpegfs_read()! virtualfile == NULL");
1152 switch (virtualfile->
m_type)
1162 size_t bytes = size;
1173 bytes_read =
static_cast<int>(bytes);
1191 cache_entry =
reinterpret_cast<Cache_Entry*
>(fi->fh);
1193 if (cache_entry ==
nullptr)
1197 Logging::error(origpath.c_str(),
"read: Tried to read from unopen file: (%1) %2", errno, strerror(errno));
1202 uint32_t frame_no = 0;
1203 std::string filename =
get_number(path, &frame_no);
1207 Logging::error(origpath.c_str(),
"read: Unable to deduct frame no. from file name (%1): (%2) %3", filename.c_str(), errno, strerror(errno));
1211 success =
transcoder_read_frame(cache_entry, buf, locoffset, size, frame_no, &bytes_read, virtualfile);
1217 cache_entry =
reinterpret_cast<Cache_Entry*
>(fi->fh);
1219 if (cache_entry ==
nullptr)
1223 Logging::error(origpath.c_str(),
"read: Tried to read from unopen file: (%1) %2", errno, strerror(errno));
1228 uint32_t segment_no = 0;
1232 std::string filename =
get_number(path, &segment_no);
1236 Logging::error(origpath.c_str(),
"read: Unable to deduct segment no. from file name (%1): (%2) %3", filename.c_str(), errno, strerror(errno));
1241 success =
transcoder_read(cache_entry, buf, locoffset, size, &bytes_read, segment_no);
1256 Logging::trace(path,
"read: Read %1 bytes from offset %2 to %3.", bytes_read, locoffset,
static_cast<size_t>(bytes_read) + locoffset);
1279 std::string origpath;
1286 if (!origpath.empty() && statvfs(origpath.c_str(), stbuf) == 0)
1300 statvfs(origpath.c_str(), stbuf);
1319 if (cache_entry !=
nullptr)
1321 uint32_t segment_no = 0;
1325 std::string filename =
get_number(path, &segment_no);
1329 Logging::error(path,
"release: Unable to deduct segment no. from file name (%1): (%2) %3", filename.c_str(), errno, strerror(errno));
1359 struct sigaction sa;
1360 std::memset(&sa, 0,
sizeof(sa));
1361 sigemptyset(&sa.sa_mask);
1362 sigaddset(&sa.sa_mask, SIGINT);
1429 if (cache_entry ==
nullptr)
1448static void init_stat(
struct stat * stbuf,
size_t fsize, time_t ftime,
bool directory)
1450 std::memset(stbuf, 0,
sizeof(
struct stat));
1452 stbuf->st_mode = DEFFILEMODE;
1455 stbuf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
1456 stbuf->st_nlink = 2;
1460 stbuf->st_mode |= S_IFREG;
1461 stbuf->st_nlink = 1;
1467 stbuf->st_uid = getuid();
1468 stbuf->st_gid = getgid();
1471 stbuf->st_atime = stbuf->st_mtime = stbuf->st_ctime = ftime;
1486static LPVIRTUALFILE make_file(
void *buf, fuse_fill_dir_t filler,
VIRTUALTYPE type,
const std::string & origpath,
const std::string & filename,
size_t fsize, time_t ftime,
int flags)
1497 return insert_file(type, origpath + filename, &stbuf, flags);
1505 std::string scriptsource;
1512 FILE *fpi = fopen(scriptsource.c_str(),
"rt");
1515 Logging::warning(scriptsource,
"File open failed. Disabling script: (%1) %2", errno, strerror(errno));
1521 if (fstat(fileno(fpi), &stbuf) == -1)
1523 Logging::warning(scriptsource,
"File could not be accessed. Disabling script: (%1) %2", errno, strerror(errno));
1528 script_file.resize(
static_cast<size_t>(stbuf.st_size));
1530 if (fread(&
script_file[0], 1,
static_cast<size_t>(stbuf.st_size), fpi) !=
static_cast<size_t>(stbuf.st_size))
1532 Logging::warning(scriptsource,
"File could not be read. Disabling script: (%1) %2", errno, strerror(errno));
1556 if (current_format !=
nullptr)
1558 *current_format =
nullptr;
1573 newvirtualfile.
m_origfile = origpath + *virtualpath;
1577 if (ffmpegfs_format !=
nullptr)
1590 newvirtualfile.
m_destfile = origpath + *virtualpath;
1593 if (lstat(newvirtualfile.
m_destfile.c_str(), &newvirtualfile.
m_st) == 0)
1611 if (current_format !=
nullptr)
1613 *current_format = ffmpegfs_format;
1630 FILENAME_MAP::const_iterator it = map.lower_bound(search_for);
1631 if (it != map.cend())
1633 const std::string & key = it->first;
1634 if (key.compare(0, search_for.size(), search_for) == 0)
1654 return insert_file(type, virtfile, virtfile, stbuf, flags);
1661 FILENAME_MAP::iterator it =
filenames.find(sanitised_virtfile);
1669 std::memcpy(&virtualfile.
m_st, stbuf,
sizeof(
struct stat));
1671 virtualfile.
m_type = type;
1683 it =
filenames.find(sanitised_virtfile);
1695 stbuf->st_mode &= ~static_cast<mode_t>(S_IFREG | S_IFLNK);
1696 stbuf->st_mode |= S_IFDIR;
1697 if (stbuf->st_mode & S_IRWXU)
1699 stbuf->st_mode |= S_IXUSR;
1701 if (stbuf->st_mode & S_IRWXG)
1703 stbuf->st_mode |= S_IXGRP;
1705 if (stbuf->st_mode & S_IRWXO)
1707 stbuf->st_mode |= S_IXOTH;
1709 stbuf->st_nlink = 2;
1710 stbuf->st_size = stbuf->st_blksize;
1733 struct stat stbufdir;
1735 std::memcpy(&stbufdir, stbuf,
sizeof(stbufdir));
1742 std::string path(virtdir);
1754 return (it !=
filenames.end() ? &it->second :
nullptr);
1763 return (it !=
rfilenames.end() ? &it->second :
nullptr);
1773int load_path(
const std::string & path,
const struct stat *statbuf,
void *buf, fuse_fill_dir_t filler)
1781 int title_count = 0;
1783 for (FILENAME_MAP::iterator it =
filenames.lower_bound(path); it !=
filenames.end(); ++it)
1785 std::string virtfilepath = it->first;
1795 #ifdef USE_LIBBLURAY
1805 if (virtfilepath == path)
1808 std::string destfile(virtualfile->
m_destfile);
1819 std::string cachefile;
1824 if (!lstat(cachefile.c_str(), &stbuf2))
1830 std::memcpy(&stbuf, &virtualfile->
m_st,
sizeof(
struct stat));
1834 if (statbuf ==
nullptr)
1836 std::memcpy(&stbuf, &virtualfile->
m_st,
sizeof(
struct stat));
1840 std::memcpy(&stbuf, statbuf,
sizeof(
struct stat));
1866 if (de->d_type & (DT_REG | DT_LNK))
1868 return (av_guess_format(
nullptr, de->d_name,
nullptr) !=
nullptr);
1888static int scandir(
const char *dirp, std::vector<struct dirent> * _namelist,
int (*
selector) (
const struct dirent *),
int (*cmp) (
const struct dirent **,
const struct dirent **))
1890 struct dirent **namelist;
1897 for (
int n = 0; n < count; n++)
1899 _namelist->push_back(*namelist[n]);
1910 std::string buffer(origpath);
1922 if (virtualfile !=
nullptr)
1933 std::string dir(*filepath);
1934 std::string searchexp(*filepath);
1935 std::string origfile;
1936 std::vector<struct dirent> namelist;
1948 if (errno != ENOTDIR)
1950 Logging::error(dir,
"Error scanning directory: (%1) %2", errno, strerror(errno));
1958 for (
size_t n = 0; n < static_cast<size_t>(count); n++)
1960 if (!strcmp(namelist[n].d_name, searchexp.c_str()))
1969 if (found && lstat(origfile.c_str(), &stbuf) == 0)
1974 if (*filepath != origfile)
1977 *filepath = origfile;
1983 return virtualfile2;
1998 std::string filepath(origpath);
2029 std::string master_contents;
2030 std::string index_0_av_contents;
2044 master_contents =
"#EXTM3U\n"
2045 "#EXT-X-STREAM-INF:PROGRAM-ID=1\n"
2046 "index_0_av.m3u8\n";
2049 "#EXT-X-TARGETDURATION:%i\n"
2050 "#EXT-X-ALLOW-CACHE:YES\n"
2051 "#EXT-X-PLAYLIST-TYPE:VOD\n"
2052 "#EXT-X-VERSION:3\n"
2058 for (uint32_t file_no = 1; file_no <= virtualfile->
get_segment_count(); file_no++)
2064 std::string cachefile;
2065 std::string _origpath(origpath);
2068 std::string filename(_origpath);
2070 filename.append(
".");
2071 filename.append(segment_name);
2075 if (!lstat(cachefile.c_str(), &stbuf))
2084 if (file_no < virtualfile->get_segment_count())
2090 strsprintf(&buffer,
"#EXTINF:%.3f,\n",
static_cast<double>(remaining_duration) / AV_TIME_BASE);
2093 index_0_av_contents += buffer;
2094 index_0_av_contents += segment_name;
2095 index_0_av_contents +=
"\n";
2098 index_0_av_contents +=
"#EXT-X-ENDLIST\n";
2102 std::copy(master_contents.begin(), master_contents.end(), std::back_inserter(child_file->
m_file_contents));
2105 std::copy(index_0_av_contents.begin(), index_0_av_contents.end(), std::back_inserter(child_file->
m_file_contents));
2109 std::string hls_html;
2115 " <title>HLS Demo</title>\n"
2116 " <script src=\"https://cdn.jsdelivr.net/npm/hls.js@latest\"></script>\n"
2117 " <meta charset=\"utf-8\">\n"
2122 " <h1>Hls.js demo - basic usage</h1>\n"
2123 " <video height=\"600\" id=\"video\" controls></video>\n"
2126 " var video = document.getElementById(\"video\");\n"
2127 " var videoSrc = \"index_0_av.m3u8\";\n"
2128 " if (Hls.isSupported()) {\n"
2129 " var hls = new Hls();\n"
2130 " hls.loadSource(videoSrc);\n"
2131 " hls.attachMedia(video);\n"
2132 " hls.on(Hls.Events.MANIFEST_PARSED, function() {\n"
2136 " // hls.js is not supported on platforms that do not have Media Source Extensions (MSE) enabled.\n"
2137 " // When the browser has built-in HLS support (check using `canPlayType`), we can provide an HLS manifest (i.e. .m3u8 URL) directly to the video element through the `src` property.\n"
2138 " // This is using the built-in support of the plain video element, without using hls.js.\n"
2139 " // Note: it would be more normal to wait on the 'canplay' event below, but on Safari (where you are most likely to find built-in HLS support), the video.src URL must be on the user-driven\n"
2140 " // white-list before a 'canplay' event will be emitted; the last video event that can be reliably listened to when the URL is not on the white-list is 'loadedmetadata'.\n"
2141 " else if (video.canPlayType(\"application/vnd.apple.mpegurl\")) {\n"
2142 " video.src = videoSrc;\n"
2143 " video.addEventListener(\"loadedmetadata\", function() {\n"
2153 std::copy(hls_html.begin(), hls_html.end(), std::back_inserter(child_file->
m_file_contents));
2172 if (virtualfile ==
nullptr)
2189 if (cache_entry ==
nullptr)
2210 if (signum == SIGINT)
2230 std::string filename(path);
2235 *value =
static_cast<uint32_t
>(std::stoi(filename));
2247 const AVOutputFormat* oformat = ::av_guess_format(
nullptr, filepath.c_str(),
nullptr);
2249 if (oformat !=
nullptr)
2259 if (
ffmpeg_format[FORMAT::VIDEO].video_codec() != AV_CODEC_ID_NONE && oformat->video_codec != AV_CODEC_ID_NONE && !
is_album_art(oformat->video_codec))
2264 else if (
ffmpeg_format[FORMAT::AUDIO].audio_codec() != AV_CODEC_ID_NONE && oformat->audio_codec != AV_CODEC_ID_NONE)
2282 AVFormatContext *format_ctx =
nullptr;
2289 res = avformat_open_input(&format_ctx, newvirtualfile->
m_origfile.c_str(),
nullptr,
nullptr);
2296 res = avformat_find_stream_info(format_ctx,
nullptr);
2304 AVDictionaryEntry *tag = av_dict_get(format_ctx->metadata,
"CUESHEET",
nullptr, AV_DICT_IGNORE_SUFFIX);
2319 if (ret != AVERROR_STREAM_NOT_FOUND)
2329 newvirtualfile->
m_duration = format_ctx->duration;
2332 if (lstat(newvirtualfile->
m_origfile.c_str(), &stbuf) == 0)
2334 std::memcpy(&newvirtualfile->
m_st, &stbuf,
sizeof(stbuf));
2337 for (
unsigned int stream_idx = 0; stream_idx < format_ctx->nb_streams; stream_idx++)
2339 switch (format_ctx->streams[stream_idx]->codecpar->codec_type)
2341 case AVMEDIA_TYPE_VIDEO:
2343 if (!
is_album_art(format_ctx->streams[stream_idx]->codecpar->codec_id))
2349 case AVMEDIA_TYPE_SUBTITLE:
2366 if (format_ctx !=
nullptr)
2368 avformat_close_input(&format_ctx);
2383 if (virtualfile !=
nullptr)
2420int add_fuse_entry(
void *buf, fuse_fill_dir_t filler,
const std::string & name,
const struct stat *stbuf, off_t )
2422 if (buf ==
nullptr || filler ==
nullptr)
2428 return filler(buf, name.c_str(), stbuf, 0,
static_cast<fuse_fill_dir_flags
>(0));
2431int add_dotdot(
void *buf, fuse_fill_dir_t filler,
const struct stat *stbuf, off_t off)
2433 struct stat *stbuf2 =
nullptr;
2436 if (stbuf !=
nullptr)
2439 init_stat(stbuf2, 0, stbuf->st_ctime,
true);
int check_bluray(const std::string &path, void *buf, fuse_fill_dir_t filler)
Get number of titles on Blu-ray.
#define CACHE_FLAG_RO
Mark cache file read-only.
bool stop_cache_maintenance()
Stop cache maintenance timer.
bool start_cache_maintenance(time_t interval)
Start cache maintenance timer.
static const std::string & make_cachefile_name(std::string *cachefile, const std::string &filename, const std::string &fileext, bool is_idx)
Make up a cache file name, including the full path.
LPVIRTUALFILE virtualfile()
Get the underlying VIRTUALFILE object.
std::unique_ptr< Buffer > m_buffer
Buffer object.
static void warning(const T filename, const std::string &format_string, Args &&...args)
Write warning level log entry.
static void debug(const T filename, const std::string &format_string, Args &&...args)
Write debug level log entry.
static void trace(const T filename, const std::string &format_string, Args &&...args)
Write trace level log entry.
static void info(const T filename, const std::string &format_string, Args &&...args)
Write info level log entry.
static void error(const T filename, const std::string &format_string, Args &&...args)
Write error level log entry.
int check_cuesheet(const std::string &filename, void *buf, fuse_fill_dir_t filler)
Get number of titles in cue sheet.
int check_dvd(const std::string &path, void *buf, fuse_fill_dir_t filler)
Get number of titles on DVD.
#define FALLTHROUGH_INTENDED
Allow fallthrough in case statements for GCC.
const std::string & remove_path(std::string *filepath)
Remove path from filename. Handy basename alternative.
void exepath(std::string *path)
Path to FFmpegfs binary.
const std::string & append_filename(std::string *path, const std::string &filename)
Add filename to path, including / after the path if required.
const std::string & remove_filename(std::string *filepath)
Remove filename from path. Handy dirname alternative.
bool check_ext(const std::string &ext, const std::string &filename)
Check if filename has a certain extension. The check is case sensitive.
bool is_blocked(const std::string &filename)
Check if filename should be hidden from output path.
std::string sanitise_filepath(std::string *filepath)
Sanitise file name. Calls realpath() to remove duplicate // or resolve ../.. etc. Changes the path in...
bool is_selected(const std::string &ext)
Find extension in include list, if existing.
int strcasecmp(const std::string &s1, const std::string &s2)
strcasecmp() equivalent for std::string.
bool is_album_art(AVCodecID codec_id, const AVRational *frame_rate)
Minimal check if codec is an album art. Requires frame_rate to decide whether this is a video stream ...
std::string make_filename(uint32_t file_no, const std::string &fileext)
Make a file name from file number and file extension.
const std::string & replace_ext(std::string *filepath, const std::string &ext)
Replace extension in filename, taking into account that there might not be an extension already.
const std::string & remove_sep(std::string *path)
Remove / from the path.
const std::string & remove_ext(std::string *filepath)
Remove extension from filename.
const std::string & append_ext(std::string *filepath, const std::string &ext)
Append extension to filename. If ext is the same as.
const std::string & append_sep(std::string *path)
Add / to the path if required.
void append_basepath(std::string *origpath, const char *path)
Translate file names from FUSE to the original absolute path.
void stat_set_size(struct stat *st, size_t size)
Properly fill in all size related members in stat struct.
int get_audio_props(AVFormatContext *format_ctx, int *channels, int *samplerate)
Get first audio stream.
std::string replace_all(std::string str, const std::string &from, const std::string &to)
Same as std::string replace(), but replaces all occurrences.
bool replace_start(std::string *str, const std::string &from, const std::string &to)
Replace start of string from "from" to "to".
bool find_ext(std::string *ext, const std::string &filename)
Find extension in filename, if existing.
std::string ffmpeg_geterror(int errnum)
Get FFmpeg error string for errnum. Internally calls av_strerror().
@ YES
Always recode to same format.
@ NO
Never recode to same format.
#define FFMPEFS_VERSION
FFmpegfs version number.
const std::string & strsprintf(std::string *str, const std::string &format, Args ... args)
Format a std::string sprintf-like.
FFMPEGFS_PARAMS params
FFmpegfs command line parameters.
FFMPEGFS_FORMAT_ARR ffmpeg_format
Two FFmpegfs_Format infos, 0: video file, 1: audio file.
void transcoder_free()
Free transcoder.
VIRTUALTYPE
Virtual file types enum.
@ DISK
Regular disk file to transcode.
@ BLURAY
Blu-ray disk file.
@ PASSTHROUGH
passthrough file, not used
#define VIRTUALFLAG_CUESHEET
File is part of a set of cue sheet tracks or the directory.
#define VIRTUALFLAG_HIDDEN
File is not transcodable or should otherwise show in listings.
#define VIRTUALFLAG_FILESET
File is file set (images, HLS)
#define VIRTUALFLAG_HLS
File is part of a set of HLS transport stream (ts) files.
#define VIRTUALFLAG_DIRECTORY
File is a virtual directory.
#define VIRTUALFLAG_NONE
No flags.
#define VIRTUALFLAG_FRAME
File is part of a set of frames.
#define VIRTUALFLAG_PASSTHROUGH
passthrough file, not used
static size_t guess_format_idx(const std::string &filepath)
Try to guess the format index (audio or video) for a file.
LPVIRTUALFILE find_file(const std::string &virtfile)
Find file in cache.
static int ffmpegfs_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
Read data from an open file.
LPVIRTUALFILE find_parent(const std::string &origpath)
Given the destination (post-transcode) file name, determine the parent of the file to be transcoded.
LPVIRTUALFILE insert_dir(VIRTUALTYPE type, const std::string &virtdir, const struct stat *stbuf, int flags)
Add new virtual directory to the internal list. If the file already exists, it will be updated.
int add_dotdot(void *buf, fuse_fill_dir_t filler, const struct stat *stbuf, off_t off)
Make dot and double dot entries for a virtual directory.
static int parse_file(LPVIRTUALFILE newvirtualfile)
Open file with FFmpeg API and parse for streams and cue sheet.
fuse_operations ffmpegfs_ops
FUSE file system operations.
int add_fuse_entry(void *buf, fuse_fill_dir_t filler, const std::string &name, const struct stat *stbuf, off_t)
Wrapper to the Fuse filler function.
std::map< const std::string, VIRTUALFILE > RFILENAME_MAP
Map source file names to virtual file objects.
static RFILENAME_MAP rfilenames
Reverse map virtual files to real files.
static int ffmpegfs_release(const char *path, struct fuse_file_info *fi)
Release an open file.
static std::vector< char > script_file
Buffer for the virtual script if enabled.
bool docker_client
True if running inside a Docker container.
static void * ffmpegfs_init(struct fuse_conn_info *conn, fuse_config *cfg)
Initialise the filesystem.
static void init_stat(struct stat *stbuf, size_t fsize, time_t ftime, bool directory)
Initialise a stat structure.
static FILENAME_MAP::const_iterator find_prefix(const FILENAME_MAP &map, const std::string &search_for)
Find mapped file by prefix. Normally used to find a path.
static int selector(const struct dirent *de)
Filter function used for scandir.
static bool virtual_name(std::string *virtualpath, const std::string &origpath="", const FFmpegfs_Format **current_format=nullptr)
Convert file name from source to destination name.
static struct sigaction oldHandler
Saves old SIGINT handler to restore on shutdown.
int load_path(const std::string &path, const struct stat *statbuf, void *buf, fuse_fill_dir_t filler)
Load a path with virtual files for FUSE.
static void stat_to_dir(struct stat *stbuf)
Convert stbuf to directory.
static int ffmpegfs_open(const char *path, struct fuse_file_info *fi)
Open a virtual or passthrough file.
static bool is_passthrough(const std::string &ext)
Check if a file should be treated passthrough, i.e. bitmaps etc.
static void sighandler(int signum)
Replacement SIGINT handler.
LPVIRTUALFILE find_original(const std::string &origpath)
Given the destination (post-transcode) file name, determine the parent of the file to be transcoded.
static void ffmpegfs_destroy(__attribute__((unused)) void *p)
Clean up filesystem.
static int get_source_properties(const std::string &origpath, LPVIRTUALFILE virtualfile)
Calculate the video frame count.
static int scandir(const char *dirp, std::vector< struct dirent > *_namelist, int(*selector)(const struct dirent *), int(*cmp)(const struct dirent **, const struct dirent **))
Scans the directory dirp Works exactly like the scandir(3) function, the only difference is that it r...
static int make_hls_fileset(void *buf, fuse_fill_dir_t filler, const std::string &origpath, LPVIRTUALFILE virtualfile)
Build a virtual HLS file set.
static int ffmpegfs_readlink(const char *path, char *buf, size_t size)
Read the target of a symbolic link.
bool check_path(const std::string &path)
Check if the path has already been parsed. Only useful if for DVD, Blu-ray or VCD where it is guarant...
static int ffmpegfs_statfs(const char *path, struct statvfs *stbuf)
Get file system statistics.
static int ffmpegfs_getattr(const char *path, struct stat *stbuf, fuse_file_info *fi)
Get file attributes.
LPVIRTUALFILE find_file_from_orig(const std::string &origfile)
Look for the file in the cache.
static std::string get_number(const char *path, uint32_t *value)
Extract the number for a file name.
LPVIRTUALFILE insert_file(VIRTUALTYPE type, const std::string &virtfile, const struct stat *stbuf, int flags)
Add new virtual file to internal list.
static FILENAME_MAP filenames
Map files to virtual files.
static void prepare_script()
Read the virtual script file into memory and store in buffer.
static int kick_next(LPVIRTUALFILE virtualfile)
Give next song in cuesheet list a kick start Starts transcoding of the next song on the cuesheet list...
static int ffmpegfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi, enum fuse_readdir_flags flags)
Read directory contents.
static void insert(const VIRTUALFILE &virtualfile)
Insert virtualfile into list.
std::map< const std::string, VIRTUALFILE > FILENAME_MAP
Map virtual file names to virtual file objects.
static const FFmpegfs_Format * get_format(LPVIRTUALFILE newvirtualfile)
Get FFmpegfs_Format for the file.
void init_fuse_ops()
Initialise FUSE operation structure.
std::unique_ptr< thread_pool > tp
Thread pool object.
static LPVIRTUALFILE make_file(void *buf, fuse_fill_dir_t filler, VIRTUALTYPE type, const std::string &origpath, const std::string &filename, size_t fsize, time_t ftime=time(nullptr), int flags=VIRTUALFLAG_NONE)
Make a virtual file.
static void flags_to_dir(int *flags)
Convert flags to directory.
Provide various log facilities to stderr, disk or syslog.
std::string m_scriptsource
Source script.
time_t m_cache_maintenance
Prune timer interval.
bool smart_transcode() const
Check for smart transcode mode.
int m_oldnamescheme
Use old output name scheme, can create duplicate filenames.
const FFmpegfs_Format * current_format(LPCVIRTUALFILE virtualfile) const
Get FFmpegfs_Format for a virtual file.
int64_t m_segment_duration
Duration of one HLS segment file, in AV_TIME_BASE fractional seconds.
RECODESAME m_recodesame
Recode to same format options.
unsigned int m_max_threads
Max. number of recoder threads.
std::string m_mountpath
Mount path: Files from m_mountpath will be mapped to this directory.
int m_enablescript
Enable virtual script.
std::string m_scriptfile
Script name.
std::string m_basepath
Base path: Files from this directory (including all sub directories) will be mapped to m_mountpath.
VIRTUALFILE * m_nextfile
Next (probable) file to be played. Used for cuesheet lists.
int m_sample_rate
Audio sample rate - Filled in for the DVD/Blu-ray directory.
std::string m_destfile
Name and path of destination file.
size_t m_predicted_size
Use this as the size instead of computing it over and over.
VIRTUALTYPE m_type
Type of this virtual file.
bool m_has_audio
True if file has an audio track.
std::string m_origfile
Sanitised name and path of original file.
int m_flags
One of the VIRTUALFLAG_* flags.
int m_channels
Audio channels - Filled in for the DVD/Blu-ray directory.
std::string m_virtfile
Name and path of virtual file.
bool m_has_video
True if file has a video track.
struct stat m_st
stat structure with size etc.
bool m_has_subtitle
True if file has a subtitle track.
std::vector< char > m_file_contents
Buffer for virtual files.
std::string m_cuesheet
Cue sheet file contents for physical file.
size_t m_format_idx
Index into params.format[] array.
struct VIRTUALFILE::CUESHEET_TRACK m_cuesheet_track
Cue sheet data for track.
uint32_t get_segment_count() const
Number of HLS segments in set.
uint32_t m_video_frame_count
Number of frames in video or 0 if not a video.
int64_t m_duration
Track/chapter duration, in AV_TIME_BASE fractional seconds.
Thread pool class implementation.
Cache_Entry * transcoder_new(LPVIRTUALFILE virtualfile, bool begin_transcode)
Allocate and initialise the transcoder.
bool transcoder_read(Cache_Entry *cache_entry, char *buff, size_t offset, size_t len, int *bytes_read, uint32_t segment_no)
Read some bytes from the internal buffer and into the given buffer.
void transcoder_exit()
Exit transcoding.
size_t transcoder_get_size(Cache_Entry *cache_entry)
Return size of output file, as computed by encoder.
bool transcoder_read_frame(Cache_Entry *cache_entry, char *buff, size_t offset, size_t len, uint32_t frame_no, int *bytes_read, LPVIRTUALFILE virtualfile)
Read one image frame from the internal buffer and into the given buffer.
bool transcoder_cached_filesize(LPVIRTUALFILE virtualfile, struct stat *stbuf)
Simply get encoded file size (do not create the whole encoder/decoder objects)
void transcoder_delete(Cache_Entry *cache_entry)
Free the cache entry structure.
File transcoder interface (for use with by FUSE)
int check_vcd(const std::string &path, void *buf, fuse_fill_dir_t filler)
Get number of chapters on S/VCD.
Video CD and Super Video CD parser.