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);
 
   84static int                          ffmpegfs_fgetattr(
const char *path, 
struct stat * stbuf, 
struct 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);
 
  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);
 
  304static int ffmpegfs_readdir(
const char *path, 
void *buf, fuse_fill_dir_t filler, off_t , 
struct fuse_file_info * )
 
  306    std::string origpath;
 
  322    if (virtualfile == 
nullptr)
 
  324#if defined(USE_LIBBLURAY) || defined(USE_LIBDVD) || defined(USE_LIBVCD) 
  333            return (res >= 0 ?  0 : res);
 
  341            return (res >= 0 ?  0 : res);
 
  349            return (res >= 0 ?  0 : res);
 
  356        DIR *dp = opendir(origpath.c_str());
 
  361                std::map<const std::string, struct stat> files;
 
  364                for (
struct dirent *de = readdir(dp); de != 
nullptr; de = readdir(dp))
 
  368                    if (lstat((origpath + de->d_name).c_str(), &stbuf) == -1)
 
  374                    files.insert({ de->d_name, stbuf });
 
  378                for (
auto& [key, value] : files)
 
  380                    std::string origname(key);
 
  387                    std::string origfile;
 
  388                    std::string filename(key);
 
  389                    struct stat & stbuf = value;
 
  392                    origfile = origpath + origname;
 
  397                    if (S_ISREG(stbuf.st_mode) || S_ISLNK(stbuf.st_mode))
 
  404                            if (current_format->
video_codec() == AV_CODEC_ID_NONE)
 
  408                                if (newvirtualfile == 
nullptr)
 
  411                                    Logging::error(origfile, 
"INTERNAL ERROR: ffmpegfs_readdir()! newvirtualfile is NULL.");
 
  420                                    Logging::debug(origfile, 
"Unable to transcode. The source has no audio stream, but the target just supports audio.");
 
  511            else if (ffmpegfs_format->
is_hls())
 
  522                load_path(origpath, 
nullptr, buf, filler);
 
  552    std::string origpath;
 
  566    if (virtualfile == 
nullptr && lstat(origpath.c_str(), stbuf) == 0)
 
  570        std::string filename(origpath);
 
  572        if (S_ISREG(stbuf->st_mode) && 
virtual_name(&filename, 
"", ¤t_format))
 
  583                Logging::trace(origpath, 
"getattr: Creating frame set directory of file.");
 
  591                else if (current_format->
is_hls())
 
  600            Logging::trace(origpath, 
"getattr: Treating existing file/directory as passthrough.");
 
  608        Logging::debug(origpath, 
"getattr: File not recoded because --recodesame=NO.");
 
  619    bool no_check = 
false;
 
  626        mempcpy(stbuf, &virtualfile->
m_st, 
sizeof(
struct stat));
 
  641        mempcpy(stbuf, &virtualfile->
m_st, 
sizeof(
struct stat));
 
  649            mempcpy(stbuf, &virtualfile->
m_st, 
sizeof(
struct stat));
 
  657            if (!no_check && lstat(origpath.c_str(), stbuf) == -1)
 
  664                if (virtualfile == 
nullptr)
 
  666                    std::string pathonly(origpath);
 
  696                            std::string origfile(origpath);
 
  732                            if (virtualfile2 == 
nullptr)
 
  738                            mempcpy(stbuf, &virtualfile2->
m_st, 
sizeof(
struct stat));
 
  764                            if (virtualfile2 == 
nullptr)
 
  770                            mempcpy(stbuf, &virtualfile2->
m_st, 
sizeof(
struct stat));
 
  782                        return (!res ?  error : res);
 
  788                if (virtualfile == 
nullptr)
 
  794                mempcpy(stbuf, &virtualfile->
m_st, 
sizeof(
struct stat));
 
  809            else if (S_ISREG(stbuf->st_mode))
 
  812                if (virtualfile == 
nullptr)
 
  821                    if (cache_entry == 
nullptr)
 
  837            mempcpy(stbuf, &virtualfile->
m_st, 
sizeof(
struct stat));
 
  862    std::string origpath;
 
  878    if ((virtualfile == 
nullptr || (virtualfile->m_flags & 
VIRTUALFLAG_PASSTHROUGH)) && lstat(origpath.c_str(), stbuf) == 0)
 
  892    bool no_check = 
false;
 
  894    switch (virtualfile->m_type)
 
  907        mempcpy(stbuf, &virtualfile->m_st, 
sizeof(
struct stat));
 
  915            mempcpy(stbuf, &virtualfile->m_st, 
sizeof(
struct stat));
 
  921                if (lstat(origpath.c_str(), stbuf) == -1)
 
  928            if (S_ISREG(stbuf->st_mode))
 
  932                if (cache_entry == 
nullptr)
 
  939                uint32_t segment_no = 0;
 
  951        mempcpy(stbuf, &virtualfile->m_st, 
sizeof(
struct stat));
 
  973    std::string origpath;
 
  983        int fd = open(origpath.c_str(), fi->flags);
 
 1007    switch (virtualfile->
m_type)
 
 1029            if (parent_file != 
nullptr)
 
 1034                if (cache_entry == 
nullptr)
 
 1040                fi->fh = 
reinterpret_cast<uintptr_t
>(cache_entry);
 
 1054            if (cache_entry == 
nullptr)
 
 1060            fi->fh = 
reinterpret_cast<uintptr_t
>(cache_entry);
 
 1090static int ffmpegfs_read(
const char *path, 
char *buf, 
size_t size, off_t offset, 
struct fuse_file_info *fi)
 
 1092    std::string origpath;
 
 1093    size_t locoffset = 
static_cast<size_t>(offset);  
 
 1096    Logging::trace(path, 
"read: Reading %1 bytes from offset %2 to %3.", size, locoffset, size + locoffset);
 
 1104        int fd = open(origpath.c_str(), O_RDONLY);
 
 1108            bytes_read = 
static_cast<int>(pread(fd, buf, size, offset));
 
 1110            if (bytes_read >= 0)
 
 1119        else if (errno != ENOENT)
 
 1132    bool success = 
true;
 
 1134    if (virtualfile == 
nullptr)
 
 1137        Logging::error(origpath.c_str(), 
"read: INTERNAL ERROR: ffmpegfs_read()! virtualfile == NULL");
 
 1141    switch (virtualfile->
m_type)
 
 1151        size_t bytes = size;
 
 1162        bytes_read = 
static_cast<int>(bytes);
 
 1180            cache_entry = 
reinterpret_cast<Cache_Entry*
>(fi->fh);
 
 1182            if (cache_entry == 
nullptr)
 
 1186                    Logging::error(origpath.c_str(), 
"read: Tried to read from unopen file: (%1) %2", errno, strerror(errno));
 
 1191            uint32_t frame_no = 0;
 
 1192            std::string filename = 
get_number(path, &frame_no);
 
 1196                Logging::error(origpath.c_str(), 
"read: Unable to deduct frame no. from file name (%1): (%2) %3", filename.c_str(), errno, strerror(errno));
 
 1200            success = 
transcoder_read_frame(cache_entry, buf, locoffset, size, frame_no, &bytes_read, virtualfile);
 
 1206            cache_entry = 
reinterpret_cast<Cache_Entry*
>(fi->fh);
 
 1208            if (cache_entry == 
nullptr)
 
 1212                    Logging::error(origpath.c_str(), 
"read: Tried to read from unopen file: (%1) %2", errno, strerror(errno));
 
 1217            uint32_t segment_no = 0;
 
 1221                std::string filename = 
get_number(path, &segment_no);
 
 1225                    Logging::error(origpath.c_str(), 
"read: Unable to deduct segment no. from file name (%1): (%2) %3", filename.c_str(), errno, strerror(errno));
 
 1230            success = 
transcoder_read(cache_entry, buf, locoffset, size, &bytes_read, segment_no);
 
 1245            Logging::trace(path, 
"read: Read %1 bytes from offset %2 to %3.", bytes_read, locoffset, 
static_cast<size_t>(bytes_read) + locoffset);
 
 1268    std::string origpath;
 
 1275    if (!origpath.empty() && statvfs(origpath.c_str(), stbuf) == 0)
 
 1289    statvfs(origpath.c_str(), stbuf);
 
 1308    if (cache_entry != 
nullptr)
 
 1310        uint32_t segment_no = 0;
 
 1314            std::string filename = 
get_number(path, &segment_no);
 
 1318                Logging::error(path, 
"release: Unable to deduct segment no. from file name (%1): (%2) %3", filename.c_str(), errno, strerror(errno));
 
 1345    struct sigaction sa;
 
 1346    std::memset(&sa, 0, 
sizeof(sa));
 
 1347    sigemptyset(&sa.sa_mask);
 
 1348    sigaddset(&sa.sa_mask, SIGINT);
 
 1353    conn->async_read = 0;
 
 1415    if (cache_entry == 
nullptr)
 
 1434static void init_stat(
struct stat * stbuf, 
size_t fsize, time_t ftime, 
bool directory)
 
 1436    std::memset(stbuf, 0, 
sizeof(
struct stat));
 
 1438    stbuf->st_mode = DEFFILEMODE; 
 
 1441        stbuf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
 
 1442        stbuf->st_nlink = 2;
 
 1446        stbuf->st_mode |= S_IFREG;
 
 1447        stbuf->st_nlink = 1;
 
 1453    stbuf->st_uid = getuid();
 
 1454    stbuf->st_gid = getgid();
 
 1457    stbuf->st_atime = stbuf->st_mtime = stbuf->st_ctime = ftime;
 
 1472static 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)
 
 1483    return insert_file(type, origpath + filename, &stbuf, flags);
 
 1491    std::string scriptsource;
 
 1498    FILE *fpi = fopen(scriptsource.c_str(), 
"rt");
 
 1501        Logging::warning(scriptsource, 
"File open failed. Disabling script: (%1) %2", errno, strerror(errno));
 
 1507        if (fstat(fileno(fpi), &stbuf) == -1)
 
 1509            Logging::warning(scriptsource, 
"File could not be accessed. Disabling script: (%1) %2", errno, strerror(errno));
 
 1514            script_file.resize(
static_cast<size_t>(stbuf.st_size));
 
 1516            if (fread(&
script_file[0], 1, 
static_cast<size_t>(stbuf.st_size), fpi) != 
static_cast<size_t>(stbuf.st_size))
 
 1518                Logging::warning(scriptsource, 
"File could not be read. Disabling script: (%1) %2", errno, strerror(errno));
 
 1542    if (current_format != 
nullptr)
 
 1544        *current_format = 
nullptr;
 
 1559    newvirtualfile.
m_origfile = origpath + *virtualpath;
 
 1563    if (ffmpegfs_format != 
nullptr)
 
 1576        newvirtualfile.
m_destfile = origpath + *virtualpath;
 
 1579        if (lstat(newvirtualfile.
m_destfile.c_str(), &newvirtualfile.
m_st) == 0)
 
 1597        if (current_format != 
nullptr)
 
 1599            *current_format = ffmpegfs_format;
 
 1616    FILENAME_MAP::const_iterator it = map.lower_bound(search_for);
 
 1617    if (it != map.cend())
 
 1619        const std::string & key = it->first;
 
 1620        if (key.compare(0, search_for.size(), search_for) == 0) 
 
 1640    return insert_file(type, virtfile, virtfile, stbuf, flags);
 
 1647    FILENAME_MAP::iterator it    = 
filenames.find(sanitised_virtfile);
 
 1655        std::memcpy(&virtualfile.
m_st, stbuf, 
sizeof(
struct stat));
 
 1657        virtualfile.
m_type              = type;
 
 1669        it = 
filenames.find(sanitised_virtfile);
 
 1681    stbuf->st_mode  &= ~static_cast<mode_t>(S_IFREG | S_IFLNK);
 
 1682    stbuf->st_mode  |= S_IFDIR;
 
 1683    if (stbuf->st_mode & S_IRWXU)
 
 1685        stbuf->st_mode  |= S_IXUSR;   
 
 1687    if (stbuf->st_mode & S_IRWXG)
 
 1689        stbuf->st_mode  |= S_IXGRP;   
 
 1691    if (stbuf->st_mode & S_IRWXO)
 
 1693        stbuf->st_mode  |= S_IXOTH;   
 
 1695    stbuf->st_nlink = 2;
 
 1696    stbuf->st_size  = stbuf->st_blksize;
 
 1719    struct stat stbufdir;
 
 1721    std::memcpy(&stbufdir, stbuf, 
sizeof(stbufdir));
 
 1728    std::string path(virtdir);
 
 1740    return (it != 
filenames.end() ? &it->second : 
nullptr);
 
 1749    return (it != 
rfilenames.end() ? &it->second : 
nullptr);
 
 1759int load_path(
const std::string & path, 
const struct stat *statbuf, 
void *buf, fuse_fill_dir_t filler)
 
 1767    int title_count = 0;
 
 1769    for (FILENAME_MAP::iterator it = 
filenames.lower_bound(path); it != 
filenames.end(); ++it)
 
 1771        std::string virtfilepath    = it->first;
 
 1781        #ifdef USE_LIBBLURAY
 
 1791        if (virtfilepath == path) 
 
 1794            std::string destfile(virtualfile->
m_destfile);
 
 1805            std::string cachefile;
 
 1810            if (!lstat(cachefile.c_str(), &stbuf2))
 
 1816                std::memcpy(&stbuf, &virtualfile->
m_st, 
sizeof(
struct stat));
 
 1820                if (statbuf == 
nullptr)
 
 1822                    std::memcpy(&stbuf, &virtualfile->
m_st, 
sizeof(
struct stat));
 
 1826                    std::memcpy(&stbuf, statbuf, 
sizeof(
struct stat));
 
 1852    if (de->d_type & (DT_REG | DT_LNK))
 
 1854        return (av_guess_format(
nullptr, de->d_name, 
nullptr) != 
nullptr);
 
 1874static int scandir(
const char *dirp, std::vector<struct dirent> * _namelist, 
int (*
selector) (
const struct dirent *), 
int (*cmp) (
const struct dirent **, 
const struct dirent **))
 
 1876    struct dirent **namelist;
 
 1883        for (
int n = 0; n < count; n++)
 
 1885            _namelist->push_back(*namelist[n]);
 
 1896    std::string buffer(origpath);
 
 1908    if (virtualfile != 
nullptr)
 
 1919            std::string dir(*filepath);
 
 1920            std::string searchexp(*filepath);
 
 1921            std::string origfile;
 
 1922            std::vector<struct dirent> namelist;
 
 1934                if (errno != ENOTDIR)   
 
 1936                    Logging::error(dir, 
"Error scanning directory: (%1) %2", errno, strerror(errno));
 
 1944            for (
size_t n = 0; n < static_cast<size_t>(count); n++)
 
 1946                if (!strcmp(namelist[n].d_name, searchexp.c_str()))
 
 1955            if (found && lstat(origfile.c_str(), &stbuf) == 0)
 
 1960                if (*filepath != origfile)
 
 1963                    *filepath = origfile;
 
 1969                return virtualfile2;
 
 1984    std::string filepath(origpath);
 
 2015        std::string master_contents;
 
 2016        std::string index_0_av_contents;
 
 2030        master_contents = 
"#EXTM3U\n" 
 2031                          "#EXT-X-STREAM-INF:PROGRAM-ID=1\n" 
 2032                          "index_0_av.m3u8\n";
 
 2035                                         "#EXT-X-TARGETDURATION:%i\n" 
 2036                                         "#EXT-X-ALLOW-CACHE:YES\n" 
 2037                                         "#EXT-X-PLAYLIST-TYPE:VOD\n" 
 2038                                         "#EXT-X-VERSION:3\n" 
 2044        for (uint32_t file_no = 1; file_no <= virtualfile->
get_segment_count(); file_no++)
 
 2050            std::string cachefile;
 
 2051            std::string _origpath(origpath);
 
 2054            std::string filename(_origpath);
 
 2056            filename.append(
".");
 
 2057            filename.append(segment_name);
 
 2061            if (!lstat(cachefile.c_str(), &stbuf))
 
 2070            if (file_no < virtualfile->get_segment_count())
 
 2076                strsprintf(&buffer, 
"#EXTINF:%.3f,\n", 
static_cast<double>(remaining_duration) / AV_TIME_BASE);
 
 2079            index_0_av_contents += buffer;
 
 2080            index_0_av_contents += segment_name;
 
 2081            index_0_av_contents += 
"\n";
 
 2084        index_0_av_contents += 
"#EXT-X-ENDLIST\n";
 
 2088        std::copy(master_contents.begin(), master_contents.end(), std::back_inserter(child_file->
m_file_contents));
 
 2091        std::copy(index_0_av_contents.begin(), index_0_av_contents.end(), std::back_inserter(child_file->
m_file_contents));
 
 2095            std::string hls_html;
 
 2101                    "    <title>HLS Demo</title>\n" 
 2102                    "    <script src=\"https://cdn.jsdelivr.net/npm/hls.js@latest\"></script>\n" 
 2103                    "    <meta charset=\"utf-8\">\n" 
 2108                    "        <h1>Hls.js demo - basic usage</h1>\n" 
 2109                    "        <video height=\"600\" id=\"video\" controls></video>\n" 
 2112                    "      var video = document.getElementById(\"video\");\n" 
 2113                    "      var videoSrc = \"index_0_av.m3u8\";\n" 
 2114                    "      if (Hls.isSupported()) {\n" 
 2115                    "        var hls = new Hls();\n" 
 2116                    "        hls.loadSource(videoSrc);\n" 
 2117                    "        hls.attachMedia(video);\n" 
 2118                    "        hls.on(Hls.Events.MANIFEST_PARSED, function() {\n" 
 2122                    "      // hls.js is not supported on platforms that do not have Media Source Extensions (MSE) enabled.\n" 
 2123                    "      // 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" 
 2124                    "      // This is using the built-in support of the plain video element, without using hls.js.\n" 
 2125                    "      // 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" 
 2126                    "      // 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" 
 2127                    "      else if (video.canPlayType(\"application/vnd.apple.mpegurl\")) {\n" 
 2128                    "        video.src = videoSrc;\n" 
 2129                    "        video.addEventListener(\"loadedmetadata\", function() {\n" 
 2139            std::copy(hls_html.begin(), hls_html.end(), std::back_inserter(child_file->
m_file_contents));
 
 2158    if (virtualfile == 
nullptr)
 
 2175    if (cache_entry == 
nullptr)
 
 2196    if (signum == SIGINT)
 
 2216    std::string filename(path);
 
 2221    *value = 
static_cast<uint32_t
>(std::stoi(filename)); 
 
 2233    const AVOutputFormat* oformat = ::av_guess_format(
nullptr, filepath.c_str(), 
nullptr);
 
 2235    if (oformat != 
nullptr)
 
 2268    AVFormatContext *format_ctx = 
nullptr;
 
 2275        res = avformat_open_input(&format_ctx, newvirtualfile->
m_origfile.c_str(), 
nullptr, 
nullptr);
 
 2282        res = avformat_find_stream_info(format_ctx, 
nullptr);
 
 2290        AVDictionaryEntry *tag = av_dict_get(format_ctx->metadata, 
"CUESHEET", 
nullptr, AV_DICT_IGNORE_SUFFIX);
 
 2305            if (ret != AVERROR_STREAM_NOT_FOUND)    
 
 2315        newvirtualfile->
m_duration = format_ctx->duration;
 
 2318        if (lstat(newvirtualfile->
m_origfile.c_str(), &stbuf) == 0)
 
 2320            std::memcpy(&newvirtualfile->
m_st, &stbuf, 
sizeof(stbuf));
 
 2323        for (
unsigned int stream_idx = 0; stream_idx < format_ctx->nb_streams; stream_idx++)
 
 2325            switch (format_ctx->streams[stream_idx]->codecpar->codec_type)
 
 2327            case AVMEDIA_TYPE_VIDEO:
 
 2329                if (!
is_album_art(format_ctx->streams[stream_idx]->codecpar->codec_id))
 
 2335            case AVMEDIA_TYPE_SUBTITLE:
 
 2352    if (format_ctx != 
nullptr)
 
 2354        avformat_close_input(&format_ctx);
 
 2369    if (virtualfile != 
nullptr)
 
 2406int add_fuse_entry(
void *buf, fuse_fill_dir_t filler, 
const std::string & name, 
const struct stat *stbuf, off_t off)
 
 2408    if (buf == 
nullptr || filler == 
nullptr)
 
 2413    return filler(buf, name.c_str(), stbuf, off);
 
 2416int add_dotdot(
void *buf, fuse_fill_dir_t filler, 
const struct stat *stbuf, off_t off)
 
 2418    struct stat *stbuf2 = 
nullptr;
 
 2421    if (stbuf != 
nullptr)
 
 2424        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.
 
@ VIDEO
FFmpegfs_Format info, 0: video file.
 
@ AUDIO
FFmpegfs_Format info, 1: audio file.
 
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.
 
VIRTUALFILE const  * LPCVIRTUALFILE
Pointer to const version of VIRTUALFILE.
 
#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.
 
static int ffmpegfs_fgetattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi)
Get attributes 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.
 
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.
 
int add_fuse_entry(void *buf, fuse_fill_dir_t filler, const std::string &name, const struct stat *stbuf, off_t off)
Wrapper to the Fuse filler function.
 
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 ffmpegfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi)
Read directory.
 
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)
File open operation.
 
static int ffmpegfs_getattr(const char *path, struct stat *stbuf)
Get file attributes.
 
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.
 
static void * ffmpegfs_init(struct fuse_conn_info *conn)
Initialise filesystem.
 
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.
 
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 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.
 
size_t transcoder_buffer_watermark(Cache_Entry *cache_entry, uint32_t segment_no)
Return the current watermark of the file while transcoding.
 
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.