FFmpegfs Fuse Multi Media Filesystem 2.19
Loading...
Searching...
No Matches
ffmpegfs.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2006-2008 David Collett
3 * Copyright (C) 2008-2012 K. Henriksson
4 * Copyright (C) 2017-2026 FFmpeg support by Norbert Schlia (nschlia@oblivion-software.de)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 *
20 * On Debian systems, the complete text of the GNU General Public License
21 * Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
22 */
23
36#ifdef __cplusplus
37extern "C" {
38#endif
39#pragma GCC diagnostic push
40#pragma GCC diagnostic ignored "-Wconversion"
41#pragma GCC diagnostic ignored "-Wsign-conversion"
42#include <libavcodec/avcodec.h>
43#include <libavformat/avformat.h>
44#include <libavfilter/avfilter.h>
45#pragma GCC diagnostic pop
46#ifdef __cplusplus
47}
48#endif
49
50#ifdef HAVE_CONFIG_H
51#include "config.h"
52#endif
53
54#include "ffmpegfs.h"
55#include "logging.h"
56#include "ffmpegfshelp.h"
57
58#include <sys/sysinfo.h>
59#include <sqlite3.h>
60#include <unistd.h>
61#include <fnmatch.h>
62#include <iostream>
63
64#ifdef USE_LIBBLURAY
65#include <libbluray/bluray-version.h>
66#endif
67
68#ifdef __clang__
69// Silence this in fuse API code for clang
70#pragma GCC diagnostic ignored "-Wimplicit-int-conversion"
71#endif
72
73#ifndef AV_PROFILE_UNKNOWN
77#define AV_PROFILE_UNKNOWN FF_PROFILE_UNKNOWN
78#endif
79
83FFMPEGFS_PARAMS::FFMPEGFS_PARAMS()
84 : m_basepath("") // required parameter
85 , m_mountpath("") // required parameter
86
87 , m_audio_codec(AV_CODEC_ID_NONE) // default: use predefined option
88 , m_video_codec(AV_CODEC_ID_NONE) // default: use predefined option
89
90 , m_autocopy(AUTOCOPY::OFF) // default: off
91 , m_recodesame(RECODESAME::NO) // default: off
92 , m_profile(PROFILE::DEFAULT) // default: no profile
93 , m_level(PRORESLEVEL::NONE) // default: no level
94
95 // Format
96 // Audio
97 , m_audiobitrate(128*1024) // default: 128 kBit
98 , m_audiosamplerate(44100) // default: 44.1 kHz
99 , m_audiochannels(2) // default: 2 channels
100 , m_sample_fmt(SAMPLE_FMT::FMT_DONTCARE) // default: use source format
101
102 // Video
103 , m_videobitrate(2*1024*1024) // default: 2 MBit
104 , m_videowidth(0) // default: do not change width
105 , m_videoheight(0) // default: do not change height
106 , m_deinterlace(0) // default: do not interlace video
107 , m_segment_duration(10 * AV_TIME_BASE) // default: 10 seconds
108 , m_min_seek_time_diff(30 * AV_TIME_BASE) // default: 30 seconds
109 // Hardware acceleration
110 , m_hwaccel_enc_API(HWACCELAPI::NONE) // default: Use software encoder
111 , m_hwaccel_enc_device_type(AV_HWDEVICE_TYPE_NONE) // default: Use software encoder
112 , m_hwaccel_dec_API(HWACCELAPI::NONE) // default: Use software encoder
113 , m_hwaccel_dec_device_type(AV_HWDEVICE_TYPE_NONE) // default: Use software decoder
114 , m_hwaccel_dec_blocked(nullptr) // default: No blocked encoders
115
116 // Subtitles
117 , m_no_subtitles(0) // default: enable subtitles
118
119 // Album arts
120 , m_noalbumarts(0) // default: copy album arts
121 // Virtual Script
122 , m_enablescript(0) // default: no virtual script
123 , m_scriptfile("index.php") // default name
124 , m_scriptsource("scripts/videotag.php") // default name
125 // Other
126 , m_debug(0) // default: no debug messages
127 , m_log_maxlevel("INFO") // default: INFO level
128 , m_log_stderr(0) // default: do not log to stderr
129 , m_log_syslog(0) // default: do not use syslog
130 , m_logfile("") // default: none
131 // Cache/recoding options
132 , m_expiry_time((60*60*24 /* d */) * 7) // default: 1 week)
133 , m_max_inactive_suspend(15) // default: 15 seconds
134 , m_max_inactive_abort(30) // default: 30 seconds
135 , m_prebuffer_time(0) // default: no prebuffer time
136 , m_prebuffer_size(100 /* KB */ * 1024) // default: 100 KB
137 , m_max_cache_size(0) // default: no limit
138 , m_min_diskspace(0) // default: no minimum
139 , m_cachepath("") // default: $XDG_CACHE_HOME/ffmpegfs
140 , m_disable_cache(0) // default: enabled
141 , m_cache_maintenance((60*60)) // default: prune every 60 minutes
142 , m_prune_cache(0) // default: Do not prune cache immediately
143 , m_clear_cache(0) // default: Do not clear cache on startup
144 , m_max_threads(0) // default: 16 * CPU cores (this value here is overwritten later)
145 , m_decoding_errors(0) // default: ignore errors
146 , m_min_dvd_chapter_duration(1) // default: 1 second
147 , m_oldnamescheme(0) // default: new scheme
148 , m_include_extensions(new (std::nothrow) MATCHVEC) // default: empty list
149 , m_hide_extensions(new (std::nothrow) MATCHVEC) // default: empty list
150 , m_win_smb_fix(1) // default: fix enabled
151{
152}
153
154FFMPEGFS_PARAMS::FFMPEGFS_PARAMS(const FFMPEGFS_PARAMS & other)
155{
156 *this = other;
157}
158
159FFMPEGFS_PARAMS::~FFMPEGFS_PARAMS()
160{
162}
163
165{
166 if (this != &other) // Self assignment check
167 {
168 m_basepath = other.m_basepath;
169 m_mountpath = other.m_mountpath;
170
171 m_audio_codec = other.m_audio_codec;
172 m_video_codec = other.m_video_codec;
173
174 m_autocopy = other.m_autocopy;
175 m_recodesame = other.m_recodesame;
176 m_profile = other.m_profile;
177 m_level = other.m_level;
178
179 m_audiobitrate = other.m_audiobitrate;
180 m_audiosamplerate = other.m_audiosamplerate;
181 m_audiochannels = other.m_audiochannels;
182 m_sample_fmt = other.m_sample_fmt;
183
184 m_videobitrate = other.m_videobitrate;
185 m_videowidth = other.m_videowidth;
186 m_videoheight = other.m_videoheight;
187 m_deinterlace = other.m_deinterlace;
188 m_segment_duration = other.m_segment_duration;
189 m_min_seek_time_diff = other.m_min_seek_time_diff;
190
191 m_hwaccel_enc_API = other.m_hwaccel_enc_API;
192 m_hwaccel_enc_device_type = other.m_hwaccel_enc_device_type;
193 m_hwaccel_enc_device = other.m_hwaccel_enc_device;
194 m_hwaccel_dec_API = other.m_hwaccel_dec_API;
195 m_hwaccel_dec_device_type = other.m_hwaccel_dec_device_type;
196 m_hwaccel_dec_device = other.m_hwaccel_dec_device;
197 m_hwaccel_dec_blocked = other.m_hwaccel_dec_blocked;
198
199 m_no_subtitles = other.m_no_subtitles;
200
201 m_noalbumarts = other.m_noalbumarts;
202
203 m_enablescript = other.m_enablescript;
204 m_scriptfile = other.m_scriptfile;
205 m_scriptsource = other.m_scriptsource;
206
207 m_debug = other.m_debug;
208 m_log_maxlevel = other.m_log_maxlevel;
209 m_log_stderr = other.m_log_stderr;
210 m_log_syslog = other.m_log_syslog;
211 m_logfile = other.m_logfile;
212
213 m_expiry_time = other.m_expiry_time;
214 m_max_inactive_suspend = other.m_max_inactive_suspend;
215 m_max_inactive_abort = other.m_max_inactive_abort;
216 m_prebuffer_time = other.m_prebuffer_time;
217 m_prebuffer_size = other.m_prebuffer_size;
218 m_max_cache_size = other.m_max_cache_size;
219 m_min_diskspace = other.m_min_diskspace;
220 m_cachepath = other.m_cachepath;
221 m_disable_cache = other.m_disable_cache;
222 m_cache_maintenance = other.m_cache_maintenance;
223 m_prune_cache = other.m_prune_cache;
224 m_clear_cache = other.m_clear_cache;
225 m_max_threads = other.m_max_threads;
226 m_decoding_errors = other.m_decoding_errors;
227 m_min_dvd_chapter_duration = other.m_min_dvd_chapter_duration;
228 m_oldnamescheme = other.m_oldnamescheme;
229 *m_include_extensions = *other.m_include_extensions;
230 *m_hide_extensions = *other.m_hide_extensions;
231 m_win_smb_fix = other.m_win_smb_fix;
232 }
233
234 return *this;
235}
236
238{
239 return (ffmpeg_format[FORMAT::AUDIO].filetype() != FILETYPE::UNKNOWN && ffmpeg_format[FORMAT::VIDEO].filetype() != ffmpeg_format[FORMAT::AUDIO].filetype());
240}
241
243{
244 if (virtualfile == nullptr || virtualfile->m_format_idx > 1)
245 {
246 return nullptr;
247 }
248 return &ffmpeg_format[virtualfile->m_format_idx];
249}
250
251enum // enum class or typedef here is not compatible with Fuse API
252{
253 KEY_HELP,
254 KEY_VERSION,
255 KEY_FFMPEG_CAPS,
256 KEY_KEEP_OPT,
257 // Intelligent parameters
258 KEY_DESTTYPE,
259 KEY_AUDIOCODEC,
260 KEY_VIDEOCODEC,
261 KEY_AUDIO_BITRATE,
262 KEY_AUDIO_SAMPLERATE,
263 KEY_AUDIO_CHANNELS,
264 KEY_AUDIO_SAMPLE_FMT,
265 KEY_VIDEO_BITRATE,
266 KEY_SEGMENT_DURATION,
267 KEY_MIN_SEEK_TIME_DIFF,
268 KEY_SCRIPTFILE,
269 KEY_SCRIPTSOURCE,
270 KEY_EXPIRY_TIME,
271 KEY_MAX_INACTIVE_SUSPEND_TIME,
272 KEY_MAX_INACTIVE_ABORT_TIME,
273 KEY_PREBUFFER_TIME,
274 KEY_PREBUFFER_SIZE,
275 KEY_MAX_CACHE_SIZE,
276 KEY_MIN_DISKSPACE_SIZE,
277 KEY_CACHEPATH,
278 KEY_CACHE_MAINTENANCE,
279 KEY_AUTOCOPY,
280 KEY_RECODESAME,
281 KEY_PROFILE,
282 KEY_LEVEL,
283 KEY_LOG_MAXLEVEL,
284 KEY_LOGFILE,
285 KEY_HWACCEL_ENCODER_API,
286 KEY_HWACCEL_ENCODER_DEVICE,
287 KEY_HWACCEL_DECODER_API,
288 KEY_HWACCEL_DECODER_DEVICE,
289 KEY_HWACCEL_DECODER_BLOCKED,
290 KEY_INCLUDE_EXTENSIONS,
291 KEY_HIDE_EXTENSIONS
292};
293
297#define FFMPEGFS_OPT(templ, param, value) { templ, offsetof(FFMPEGFS_PARAMS, param), value }
298
304#pragma GCC diagnostic push
305#pragma GCC diagnostic ignored "-Wnarrowing"
306#pragma GCC diagnostic ignored "-Wsign-conversion"
307static struct fuse_opt ffmpegfs_opts[] = // NOLINT(modernize-avoid-c-arrays)
308{
309 // Output type
310 FUSE_OPT_KEY("--desttype=%s", KEY_DESTTYPE),
311 FUSE_OPT_KEY("desttype=%s", KEY_DESTTYPE),
312 FUSE_OPT_KEY("--audiocodec=%s", KEY_AUDIOCODEC),
313 FUSE_OPT_KEY("audiocodec=%s", KEY_AUDIOCODEC),
314 FUSE_OPT_KEY("--videocodec=%s", KEY_VIDEOCODEC),
315 FUSE_OPT_KEY("videocodec=%s", KEY_VIDEOCODEC),
316 FUSE_OPT_KEY("--profile=%s", KEY_PROFILE),
317 FUSE_OPT_KEY("profile=%s", KEY_PROFILE),
318 FUSE_OPT_KEY("--autocopy=%s", KEY_AUTOCOPY),
319 FUSE_OPT_KEY("autocopy=%s", KEY_AUTOCOPY),
320 FUSE_OPT_KEY("--recodesame=%s", KEY_RECODESAME),
321 FUSE_OPT_KEY("recodesame=%s", KEY_RECODESAME),
322 FUSE_OPT_KEY("--level=%s", KEY_LEVEL),
323 FUSE_OPT_KEY("level=%s", KEY_LEVEL),
324
325 // Audio
326 FUSE_OPT_KEY("--audiobitrate=%s", KEY_AUDIO_BITRATE),
327 FUSE_OPT_KEY("audiobitrate=%s", KEY_AUDIO_BITRATE),
328 FUSE_OPT_KEY("--audiosamplerate=%s", KEY_AUDIO_SAMPLERATE),
329 FUSE_OPT_KEY("audiosamplerate=%s", KEY_AUDIO_SAMPLERATE),
330 FUSE_OPT_KEY("--audiochannels=%s", KEY_AUDIO_CHANNELS),
331 FUSE_OPT_KEY("audiochannels=%s", KEY_AUDIO_CHANNELS),
332 FUSE_OPT_KEY("--audiosamplefmt=%s", KEY_AUDIO_SAMPLE_FMT),
333 FUSE_OPT_KEY("audiosamplefmt=%s", KEY_AUDIO_SAMPLE_FMT),
334 // Video
335 FUSE_OPT_KEY("--videobitrate=%s", KEY_VIDEO_BITRATE),
336 FUSE_OPT_KEY("videobitrate=%s", KEY_VIDEO_BITRATE),
337 FFMPEGFS_OPT("--videoheight=%u", m_videoheight, 0),
338 FFMPEGFS_OPT("videoheight=%u", m_videoheight, 0),
339 FFMPEGFS_OPT("--videowidth=%u", m_videowidth, 0),
340 FFMPEGFS_OPT("videowidth=%u", m_videowidth, 0),
341 FFMPEGFS_OPT("--deinterlace", m_deinterlace, 1),
342 FFMPEGFS_OPT("deinterlace", m_deinterlace, 1),
343 // HLS
344 FUSE_OPT_KEY("--segment_duration=%s", KEY_SEGMENT_DURATION),
345 FUSE_OPT_KEY("segment_duration=%s", KEY_SEGMENT_DURATION),
346 FUSE_OPT_KEY("--min_seek_time_diff=%s", KEY_MIN_SEEK_TIME_DIFF),
347 FUSE_OPT_KEY("min_seek_time_diff=%s", KEY_MIN_SEEK_TIME_DIFF),
348 // Hardware acceleration
349 FUSE_OPT_KEY("--hwaccel_enc=%s", KEY_HWACCEL_ENCODER_API),
350 FUSE_OPT_KEY("hwaccel_enc=%s", KEY_HWACCEL_ENCODER_API),
351 FUSE_OPT_KEY("--hwaccel_enc_device=%s", KEY_HWACCEL_ENCODER_DEVICE),
352 FUSE_OPT_KEY("hwaccel_enc_device=%s", KEY_HWACCEL_ENCODER_DEVICE),
353 FUSE_OPT_KEY("--hwaccel_dec=%s", KEY_HWACCEL_DECODER_API),
354 FUSE_OPT_KEY("hwaccel_dec=%s", KEY_HWACCEL_DECODER_API),
355 FUSE_OPT_KEY("--hwaccel_dec_device=%s", KEY_HWACCEL_DECODER_DEVICE),
356 FUSE_OPT_KEY("hwaccel_dec_device=%s", KEY_HWACCEL_DECODER_DEVICE),
357 FUSE_OPT_KEY("--hwaccel_dec_blocked=%s", KEY_HWACCEL_DECODER_BLOCKED),
358 FUSE_OPT_KEY("hwaccel_dec_blocked=%s", KEY_HWACCEL_DECODER_BLOCKED),
359 // Subtitles
360 FFMPEGFS_OPT("--no_subtitles", m_no_subtitles, 1),
361 FFMPEGFS_OPT("no_subtitles", m_no_subtitles, 1),
362 // Album arts
363 FFMPEGFS_OPT("--noalbumarts", m_noalbumarts, 1),
364 FFMPEGFS_OPT("noalbumarts", m_noalbumarts, 1),
365 // Virtual script
366 FFMPEGFS_OPT("--enablescript", m_enablescript, 1),
367 FFMPEGFS_OPT("enablescript", m_enablescript, 1),
368 FUSE_OPT_KEY("--scriptfile=%s", KEY_SCRIPTFILE),
369 FUSE_OPT_KEY("scriptfile=%s", KEY_SCRIPTFILE),
370 FUSE_OPT_KEY("--scriptsource=%s", KEY_SCRIPTSOURCE),
371 FUSE_OPT_KEY("scriptsource=%s", KEY_SCRIPTSOURCE),
372 // Background recoding/caching
373 // Cache
374 FUSE_OPT_KEY("--expiry_time=%s", KEY_EXPIRY_TIME),
375 FUSE_OPT_KEY("expiry_time=%s", KEY_EXPIRY_TIME),
376 FUSE_OPT_KEY("--max_inactive_suspend=%s", KEY_MAX_INACTIVE_SUSPEND_TIME),
377 FUSE_OPT_KEY("max_inactive_suspend=%s", KEY_MAX_INACTIVE_SUSPEND_TIME),
378 FUSE_OPT_KEY("--max_inactive_abort=%s", KEY_MAX_INACTIVE_ABORT_TIME),
379 FUSE_OPT_KEY("max_inactive_abort=%s", KEY_MAX_INACTIVE_ABORT_TIME),
380 FUSE_OPT_KEY("--prebuffer_time=%s", KEY_PREBUFFER_TIME),
381 FUSE_OPT_KEY("prebuffer_time=%s", KEY_PREBUFFER_TIME),
382 FUSE_OPT_KEY("--prebuffer_size=%s", KEY_PREBUFFER_SIZE),
383 FUSE_OPT_KEY("prebuffer_size=%s", KEY_PREBUFFER_SIZE),
384 FUSE_OPT_KEY("--max_cache_size=%s", KEY_MAX_CACHE_SIZE),
385 FUSE_OPT_KEY("max_cache_size=%s", KEY_MAX_CACHE_SIZE),
386 FUSE_OPT_KEY("--min_diskspace=%s", KEY_MIN_DISKSPACE_SIZE),
387 FUSE_OPT_KEY("min_diskspace=%s", KEY_MIN_DISKSPACE_SIZE),
388 FUSE_OPT_KEY("--cachepath=%s", KEY_CACHEPATH),
389 FUSE_OPT_KEY("cachepath=%s", KEY_CACHEPATH),
390 FFMPEGFS_OPT("--disable_cache", m_disable_cache, 1),
391 FFMPEGFS_OPT("disable_cache", m_disable_cache, 1),
392 FUSE_OPT_KEY("--cache_maintenance=%s", KEY_CACHE_MAINTENANCE),
393 FUSE_OPT_KEY("cache_maintenance=%s", KEY_CACHE_MAINTENANCE),
394 FFMPEGFS_OPT("--prune_cache", m_prune_cache, 1),
395 FFMPEGFS_OPT("--clear_cache", m_clear_cache, 1),
396 FFMPEGFS_OPT("clear_cache", m_clear_cache, 1),
397
398 // Other
399 FFMPEGFS_OPT("--max_threads=%u", m_max_threads, 0),
400 FFMPEGFS_OPT("max_threads=%u", m_max_threads, 0),
401 FFMPEGFS_OPT("--decoding_errors=%u", m_decoding_errors, 0),
402 FFMPEGFS_OPT("decoding_errors=%u", m_decoding_errors, 0),
403 FFMPEGFS_OPT("--min_dvd_chapter_duration=%u", m_min_dvd_chapter_duration, 0),
404 FFMPEGFS_OPT("min_dvd_chapter_duration=%u", m_min_dvd_chapter_duration, 0),
405 FFMPEGFS_OPT("--oldnamescheme=%u", m_oldnamescheme, 0),
406 FFMPEGFS_OPT("oldnamescheme=%u", m_oldnamescheme, 0),
407 FUSE_OPT_KEY("--include_extensions=%s", KEY_INCLUDE_EXTENSIONS),
408 FUSE_OPT_KEY("include_extensions=%s", KEY_INCLUDE_EXTENSIONS),
409 FUSE_OPT_KEY("--hide_extensions=%u", KEY_HIDE_EXTENSIONS),
410 FUSE_OPT_KEY("hide_extensions=%u", KEY_HIDE_EXTENSIONS),
411 // Experimental
412 FFMPEGFS_OPT("--win_smb_fix=%u", m_win_smb_fix, 1),
413 FFMPEGFS_OPT("win_smb_fix=%u", m_win_smb_fix, 1),
414 // FFmpegfs options
415 FFMPEGFS_OPT("-d", m_debug, 1),
416 FFMPEGFS_OPT("debug", m_debug, 1),
417 FUSE_OPT_KEY("--log_maxlevel=%s", KEY_LOG_MAXLEVEL),
418 FUSE_OPT_KEY("log_maxlevel=%s", KEY_LOG_MAXLEVEL),
419 FFMPEGFS_OPT("--log_stderr", m_log_stderr, 1),
420 FFMPEGFS_OPT("log_stderr", m_log_stderr, 1),
421 FFMPEGFS_OPT("--log_syslog", m_log_syslog, 1),
422 FFMPEGFS_OPT("log_syslog", m_log_syslog, 1),
423 FUSE_OPT_KEY("--logfile=%s", KEY_LOGFILE),
424 FUSE_OPT_KEY("logfile=%s", KEY_LOGFILE),
425
426 FUSE_OPT_KEY("-h", KEY_HELP),
427 FUSE_OPT_KEY("--help", KEY_HELP),
428 FUSE_OPT_KEY("-V", KEY_VERSION),
429 FUSE_OPT_KEY("--version", KEY_VERSION),
430 FUSE_OPT_KEY("-c", KEY_FFMPEG_CAPS),
431 FUSE_OPT_KEY("--capabilities", KEY_FFMPEG_CAPS),
432 FUSE_OPT_KEY("-d", KEY_KEEP_OPT),
433 FUSE_OPT_KEY("debug", KEY_KEEP_OPT),
434 FUSE_OPT_END
435};
436#pragma GCC diagnostic pop
437
438typedef std::map<const std::string, const AUTOCOPY, comp> AUTOCOPY_MAP;
439typedef std::map<const std::string, const PROFILE, comp> PROFILE_MAP;
440typedef std::map<const std::string, const PRORESLEVEL, comp> LEVEL_MAP;
441typedef std::map<const std::string, const RECODESAME, comp> RECODESAME_MAP;
449
450typedef std::map<const std::string, HWACCEL, comp> HWACCEL_MAP;
451typedef std::map<const std::string, const AVCodecID, comp> CODEC_MAP;
452typedef std::map<const std::string, const SAMPLE_FMT, comp> SAMPLE_FMT_MAP;
454typedef std::map<const std::string, const AVCodecID, comp> AUDIOCODEC_MAP;
455typedef std::map<const std::string, const AVCodecID, comp> VIDEOCODEC_MAP;
461{
462 { "AAC", AV_CODEC_ID_AAC }, // TS, MP4, MOV, MKV
463 { "AC3", AV_CODEC_ID_AC3 }, // MP4, MOV, MKV
464 { "MP3", AV_CODEC_ID_MP3 }, // TS, MP4, MOV, MKV
465 { "OPUS", AV_CODEC_ID_OPUS }, // webm
466
467 { "VORBIS", AV_CODEC_ID_VORBIS },
468 { "DTS", AV_CODEC_ID_DTS },
469 { "PCM16", AV_CODEC_ID_PCM_S16LE },
470 { "PCM24", AV_CODEC_ID_PCM_S24LE },
471 { "PCM32", AV_CODEC_ID_PCM_S32LE },
472};
473
478{
479 { "MPEG1", AV_CODEC_ID_MPEG1VIDEO }, // TS, MP4, MKV
480 { "MPEG2", AV_CODEC_ID_MPEG2VIDEO }, // TS, MP4, MKV
481 { "H264", AV_CODEC_ID_H264 }, // TS, MP4, MKV
482 { "H265", AV_CODEC_ID_H265 }, // TS, MP4, MKV
483 { "VP8", AV_CODEC_ID_VP8 }, // WebM
484 { "VP9", AV_CODEC_ID_VP9 }, // WebM
485
486 //{ "AV1", AV_CODEC_ID_AV1 }, /** @todo WebM ends with "Could not write video frame (error 'Invalid data found when processing input')." */
487};
488
493{
494 { "OFF", AUTOCOPY::OFF },
495 { "MATCH", AUTOCOPY::MATCH },
496 { "MATCHLIMIT", AUTOCOPY::MATCHLIMIT },
497 { "STRICT", AUTOCOPY::STRICT },
498 { "STRICTLIMIT", AUTOCOPY::STRICTLIMIT },
499};
500
505{
506 { "NONE", PROFILE::DEFAULT },
507
508 // MP4
509
510 { "FF", PROFILE::MP4_FF },
511 { "EDGE", PROFILE::MP4_EDGE },
512 { "IE", PROFILE::MP4_IE },
513 { "CHROME", PROFILE::MP4_CHROME },
514 { "SAFARI", PROFILE::MP4_SAFARI },
515 { "OPERA", PROFILE::MP4_OPERA },
516 { "MAXTHON", PROFILE::MP4_MAXTHON },
517
518 // ALAC
519
520 { "ITUNES", PROFILE::ALAC_ITUNES },
521
522 // WEBM
523};
524
529{
530 // ProRes
531 { "PROXY", PRORESLEVEL::PRORES_PROXY },
532 { "LT", PRORESLEVEL::PRORES_LT },
533 { "STANDARD", PRORESLEVEL::PRORES_STANDARD },
534 { "HQ", PRORESLEVEL::PRORES_HQ },
535};
536
541{
542 // Recode to same format
543 { "NO", RECODESAME::NO },
544 { "YES", RECODESAME::YES },
545};
546
556{
557 { "NONE", { true, HWACCELAPI::NONE, AV_HWDEVICE_TYPE_NONE } },
558
559 // **** Supported by Linux ****
560
561 { "VAAPI", { true, HWACCELAPI::VAAPI, AV_HWDEVICE_TYPE_NONE } }, // Video Acceleration API (VA-API), https://trac.ffmpeg.org/wiki/Hardware/VAAPI
562
563 // RaspberryPi
564
565 { "MMAL", { true, HWACCELAPI::MMAL, AV_HWDEVICE_TYPE_NONE } }, // Multimedia Abstraction Layer by Broadcom. Encoding only.
566 { "OMX", { true, HWACCELAPI::OMX, AV_HWDEVICE_TYPE_NONE } }, // OpenMAX (Open Media Acceleration). Decoding only.
567
568 #if 0
569 // Additional formats
570 { "CUDA", { false, HWACCELAPI::CUDA, AV_HWDEVICE_TYPE_NONE } }, // Compute Unified Device Architecture, see https://developer.nvidia.com/ffmpeg and https://en.wikipedia.org/wiki/CUDA
571 { "V4L2M2M", { false, HWACCELAPI::V4L2M2M, AV_HWDEVICE_TYPE_NONE } }, // v4l2 mem to mem (Video4linux)
572 { "VDPAU", { false, HWACCELAPI::VDPAU, AV_HWDEVICE_TYPE_NONE } }, // Video Decode and Presentation API for Unix, see https://en.wikipedia.org/wiki/VDPAU
573 { "QSV", { false, HWACCELAPI::QSV, AV_HWDEVICE_TYPE_NONE } }, // QuickSync, see https://trac.ffmpeg.org/wiki/Hardware/QuickSync
574 { "OPENCL", { false, HWACCELAPI::OPENCL, AV_HWDEVICE_TYPE_NONE } }, // Open Standard for Parallel Programming of Heterogeneous Systems, see https://trac.ffmpeg.org/wiki/HWAccelIntro#OpenCL
575 #if HAVE_VULKAN_HWACCEL
576 { "VULKAN", { false, HWACCELAPI::VULKAN, AV_HWDEVICE_TYPE_NONE } }, // Low-overhead, cross-platform 3D graphics and computing API, requires Libavutil >= 56.30.100, see https://en.wikipedia.org/wiki/Vulkan_(API)
577 #endif // HAVE_VULKAN_HWACCEL
578 #if __APPLE__
579 // MacOS, not supported
580 { "VIDEOTOOLBOX", { false, HWACCELAPI::VIDEOTOOLBOX, AV_HWDEVICE_TYPE_NONE } }, // https://trac.ffmpeg.org/wiki/HWAccelIntro#VideoToolbox
581 #endif
582 #if __ANDROID__
583 // Android
584 { "MEDIACODEC", { false, HWACCELAPI::MEDIACODEC, AV_HWDEVICE_TYPE_NONE } }, // See https://developer.android.com/reference/android/media/MediaCodec
585 #endif
586 #if _WIN32
587 // **** Not supported ****
588
589 // Digital Rights Management
590 { "DRM", { false, HWACCELAPI::DRM, AV_HWDEVICE_TYPE_NONE } },
591
592 // Windows only, not supported
593 { "DXVA2", { false, HWACCELAPI::DXVA2, AV_HWDEVICE_TYPE_NONE } }, // Direct3D 9 / DXVA2
594 { "D3D11VA", { false, HWACCELAPI::D3D11VA, AV_HWDEVICE_TYPE_NONE } }, // Direct3D 11
595 #endif
596 #endif
597};
598
603{
604 { "H263", AV_CODEC_ID_H263 },
605 { "H264", AV_CODEC_ID_H264 },
606 { "HEVC", AV_CODEC_ID_HEVC },
607 { "MPEG2", AV_CODEC_ID_MPEG2VIDEO },
608 { "MPEG4", AV_CODEC_ID_MPEG4 },
609 { "VC1", AV_CODEC_ID_VC1 },
610 { "VP8", AV_CODEC_ID_VP8 },
611 { "VP9", AV_CODEC_ID_VP9 },
612 { "WMV3", AV_CODEC_ID_WMV3 },
613};
614
619{
621 { "8", SAMPLE_FMT::FMT_8 },
622 { "16", SAMPLE_FMT::FMT_16 },
623 { "24", SAMPLE_FMT::FMT_24 },
624 { "32", SAMPLE_FMT::FMT_32 },
625 { "64", SAMPLE_FMT::FMT_64 },
626 { "F16", SAMPLE_FMT::FMT_F16 },
627 { "F24", SAMPLE_FMT::FMT_F24 },
628 { "F32", SAMPLE_FMT::FMT_F32 },
629 { "F64", SAMPLE_FMT::FMT_F64 },
630};
631
632static int get_bitrate(const std::string & arg, BITRATE *bitrate);
633static int get_samplerate(const std::string & arg, int * samplerate);
634static int get_sampleformat(const std::string & arg, SAMPLE_FMT * sample_fmt);
635static int get_time(const std::string & arg, time_t *time);
636static int get_size(const std::string & arg, size_t *size);
637static int get_desttype(const std::string & arg, FFMPEGFS_FORMAT_ARR & format);
638static int get_audiocodec(const std::string & arg, AVCodecID *audio_codec);
639static int get_videocodec(const std::string & arg, AVCodecID *video_codec);
640static int get_autocopy(const std::string & arg, AUTOCOPY *autocopy);
641static int get_recodesame(const std::string & arg, RECODESAME *recode);
642static int get_profile(const std::string & arg, PROFILE *profile);
643static int get_level(const std::string & arg, PRORESLEVEL *level);
644static int get_segment_duration(const std::string & arg, int64_t *value);
645static int get_seek_time_diff(const std::string & arg, int64_t *value);
646static int get_hwaccel(const std::string & arg, HWACCELAPI *hwaccel_API, AVHWDeviceType *hwaccel_device_type);
647static int get_codec(const std::string & codec, AVCodecID *codec_id);
648static int get_hwaccel_dec_blocked(const std::string & arg, HWACCEL_BLOCKED_MAP **hwaccel_dec_blocked);
649static int get_value(const std::string & arg, int *value);
650static int get_value(const std::string & arg, std::string *value);
651static int get_value(const std::string & arg, MATCHVEC *value);
652//static int get_value(const std::string & arg, std::optional<std::string> *value);
653static int get_value(const std::string & arg, double *value);
654
655static int ffmpegfs_opt_proc(__attribute__((unused)) void* data, const char* arg, int key, struct fuse_args *outargs);
656static bool set_defaults();
657static void build_device_type_list();
658static void print_params();
659static void usage();
660static void ffmpeg_log(void *ptr, int level, const char *fmt, va_list vl);
661static bool init_logging(const std::string &logfile, const std::string & max_level, bool to_stderr, bool to_syslog);
662
666static void usage()
667{
668 std::string help;
669 size_t pos;
670
671 help.assign(reinterpret_cast<const char*>(ffmpegfshelp), ffmpegfshelp_len);
672 pos = help.find("OPTIONS\n");
673
674 std::cout << help.substr(pos + sizeof("OPTIONS\n"));
675}
676
682template<typename T>
683static void list_options(const char * info, const T & map)
684{
685 std::string buffer;
686 for (typename T::const_iterator it = map.cbegin(); it != map.cend();)
687 {
688 buffer += it->first.c_str();
689
690 if (++it != map.cend())
691 {
692 buffer += ", ";
693 }
694 }
695
696 if (info != nullptr)
697 {
698 std::fprintf(stderr, "%s: %s\n", info, buffer.c_str());
699 }
700 else
701 {
702 std::fprintf(stderr, "%s\n", buffer.c_str());
703 }
704}
705
718static int get_bitrate(const std::string & arg, BITRATE *bitrate)
719{
720 size_t pos = arg.find('=');
721
722 if (pos != std::string::npos)
723 {
724 std::string param(arg.substr(0, pos));
725 std::string data(arg.substr(pos + 1));
726 int reti;
727
728 // Check for decimal number
729 reti = reg_compare(data, "^([1-9][0-9]*|0)?(bps)?$", std::regex::icase);
730
731 if (reti == -1)
732 {
733 return -1;
734 }
735 else if (!reti)
736 {
737 *bitrate = static_cast<BITRATE>(std::stol(data));
738 return 0; // OK
739 }
740
741 // Check for number with optional descimal point and K modifier
742 reti = reg_compare(data, "^[1-9][0-9]*(\\.[0-9]+)?K(bps)?$", std::regex::icase);
743
744 if (reti == -1)
745 {
746 return -1;
747 }
748 else if (!reti)
749 {
750 *bitrate = static_cast<BITRATE>(std::stof(data) * 1000);
751 return 0; // OK
752 }
753
754 // Check for number with optional descimal point and M modifier
755 reti = reg_compare(data, "^[1-9][0-9]*(\\.[0-9]+)?M(bps)?$", std::regex::icase);
756
757 if (reti == -1)
758 {
759 return -1;
760 }
761 else if (!reti)
762 {
763 *bitrate = static_cast<BITRATE>(std::stof(data) * 1000000);
764 return 0; // OK
765 }
766
767 std::fprintf(stderr, "INVALID PARAMETER (%s): Invalid bit rate '%s'\n", param.c_str(), data.c_str());
768 }
769
770 std::fprintf(stderr, "INVALID PARAMETER (%s): Missing argument\n", arg.c_str());
771
772 return -1;
773}
774
786static int get_samplerate(const std::string & arg, int * samplerate)
787{
788 size_t pos = arg.find('=');
789
790 if (pos != std::string::npos)
791 {
792 std::string param(arg.substr(0, pos));
793 std::string data(arg.substr(pos + 1));
794 int reti;
795
796 // Check for decimal number
797 reti = reg_compare(data, "^([1-9][0-9]*|0)(Hz)?$", std::regex::icase);
798
799 if (reti == -1)
800 {
801 return -1;
802 }
803 else if (!reti)
804 {
805 *samplerate = std::stoi(data);
806 return 0; // OK
807 }
808
809 // Check for number with optional descimal point and K modifier
810 reti = reg_compare(data, "^[1-9][0-9]*(\\.[0-9]+)?K(Hz)?$", std::regex::icase);
811
812 if (reti == -1)
813 {
814 return -1;
815 }
816 else if (!reti)
817 {
818 *samplerate = static_cast<int>(std::stof(data) * 1000);
819 return 0; // OK
820 }
821
822 std::fprintf(stderr, "INVALID PARAMETER (%s): Invalid sample rate '%s'\n", param.c_str(), data.c_str());
823 }
824 else
825 {
826 std::fprintf(stderr, "INVALID PARAMETER (%s): Missing argument\n", arg.c_str());
827 }
828
829 return -1;
830}
831
838static int get_sampleformat(const std::string & arg, SAMPLE_FMT * sample_fmt)
839{
840 size_t pos = arg.find('=');
841
842 *sample_fmt = SAMPLE_FMT::FMT_DONTCARE;
843
844 if (pos != std::string::npos)
845 {
846 std::string param(arg.substr(0, pos));
847 std::string data(arg.substr(pos + 1));
848
849 SAMPLE_FMT_MAP::const_iterator it = sample_fmt_map.find(data);
850
851 if (it == sample_fmt_map.cend())
852 {
853 std::fprintf(stderr, "INVALID PARAMETER (%s): Invalid sample format option: %s\n", param.c_str(), data.c_str());
854
855 list_options("Valid sample formats are", sample_fmt_map);
856
857 return -1;
858 }
859
860 // May fail later: Can only be checked when destination format is known.
861 *sample_fmt = it->second;
862
863 return 0;
864 }
865
866 std::fprintf(stderr, "INVALID PARAMETER (%s): Missing argument\n", arg.c_str());
867
868 return -1;
869
870}
871
872std::string get_sampleformat_text(SAMPLE_FMT sample_fmt)
873{
874 SAMPLE_FMT_MAP::const_iterator it = search_by_value(sample_fmt_map, sample_fmt);
875 if (it != sample_fmt_map.cend())
876 {
877 return it->first;
878 }
879 return "INVALID";
880}
881
896static int get_time(const std::string & arg, time_t *time)
897{
898 size_t pos = arg.find('=');
899
900 if (pos != std::string::npos)
901 {
902 std::string param(arg.substr(0, pos));
903 std::string data(arg.substr(pos + 1));
904 int reti;
905
906 // Check for decimal number
907 reti = reg_compare(data, "^([1-9][0-9]*|0)?s?$", std::regex::icase);
908
909 if (reti == -1)
910 {
911 return -1;
912 }
913 else if (!reti)
914 {
915 *time = static_cast<time_t>(std::stol(data));
916 return 0; // OK
917 }
918
919 // Check for number with optional descimal point and m modifier
920 reti = reg_compare(data, "^[1-9][0-9]*(\\.[0-9]+)?m$", std::regex::icase);
921
922 if (reti == -1)
923 {
924 return -1;
925 }
926 else if (!reti)
927 {
928 *time = static_cast<time_t>(std::stof(data) * 60);
929 return 0; // OK
930 }
931
932 // Check for number with optional descimal point and h modifier
933 reti = reg_compare(data, "^[1-9][0-9]*(\\.[0-9]+)?h$", std::regex::icase);
934
935 if (reti == -1)
936 {
937 return -1;
938 }
939 else if (!reti)
940 {
941 *time = static_cast<time_t>(std::stof(data) * 60 * 60);
942 return 0; // OK
943 }
944
945 // Check for number with optional descimal point and d modifier
946 reti = reg_compare(data, "^[1-9][0-9]*(\\.[0-9]+)?d$", std::regex::icase);
947
948 if (reti == -1)
949 {
950 return -1;
951 }
952 else if (!reti)
953 {
954 *time = static_cast<time_t>(std::stof(data) * 60 * 60 * 24);
955 return 0; // OK
956 }
957
958 // Check for number with optional descimal point and w modifier
959 reti = reg_compare(data, "^[1-9][0-9]*(\\.[0-9]+)?w$", std::regex::icase);
960
961 if (reti == -1)
962 {
963 return -1;
964 }
965 else if (!reti)
966 {
967 *time = static_cast<time_t>(std::stof(data) * 60 * 60 * 24 * 7);
968 return 0; // OK
969 }
970
971 std::fprintf(stderr, "INVALID PARAMETER (%s): Invalid time format '%s'\n", param.c_str(), data.c_str());
972 }
973 else
974 {
975 std::fprintf(stderr, "INVALID PARAMETER (%s): Invalid time format\n", arg.c_str());
976 }
977
978 return -1;
979}
980
995static int get_size(const std::string & arg, size_t *size)
996{
997 size_t pos = arg.find('=');
998
999 if (pos != std::string::npos)
1000 {
1001 std::string param(arg.substr(0, pos));
1002 std::string data(arg.substr(pos + 1));
1003 int reti;
1004
1005 // Check for decimal number
1006 reti = reg_compare(data, "^([1-9][0-9]*|0)?B?$", std::regex::icase);
1007
1008 if (reti == -1)
1009 {
1010 return -1;
1011 }
1012 else if (!reti)
1013 {
1014 *size = static_cast<size_t>(std::stol(data));
1015 return 0; // OK
1016 }
1017
1018 // Check for number with optional descimal point and K/KB modifier
1019 reti = reg_compare(data, "^[1-9][0-9]*(\\.[0-9]+)?KB?$", std::regex::icase);
1020
1021 if (reti == -1)
1022 {
1023 return -1;
1024 }
1025 else if (!reti)
1026 {
1027 *size = static_cast<size_t>(std::stof(data) * 1024);
1028 return 0; // OK
1029 }
1030
1031 // Check for number with optional descimal point and M/MB modifier
1032 reti = reg_compare(data, "^[1-9][0-9]*(\\.[0-9]+)?MB?$", std::regex::icase);
1033
1034 if (reti == -1)
1035 {
1036 return -1;
1037 }
1038 else if (!reti)
1039 {
1040 *size = static_cast<size_t>(std::stof(data) * 1024 * 1024);
1041 return 0; // OK
1042 }
1043
1044 // Check for number with optional descimal point and G/GB modifier
1045 reti = reg_compare(data, "^[1-9][0-9]*(\\.[0-9]+)?GB?$", std::regex::icase);
1046
1047 if (reti == -1)
1048 {
1049 return -1;
1050 }
1051 else if (!reti)
1052 {
1053 *size = static_cast<size_t>(std::stof(data) * 1024 * 1024 * 1024);
1054 return 0; // OK
1055 }
1056
1057 // Check for number with optional descimal point and T/TB modifier
1058 reti = reg_compare(data, "^[1-9][0-9]*(\\.[0-9]+)?TB?$", std::regex::icase);
1059
1060 if (reti == -1)
1061 {
1062 return -1;
1063 }
1064 else if (!reti)
1065 {
1066 *size = static_cast<size_t>(std::stof(data) * 1024 * 1024 * 1024 * 1024);
1067 return 0; // OK
1068 }
1069
1070 std::fprintf(stderr, "INVALID PARAMETER (%s): Invalid size '%s'\n", param.c_str(), data.c_str());
1071 }
1072 else
1073 {
1074 std::fprintf(stderr, "INVALID PARAMETER (%s): Invalid size\n", arg.c_str());
1075 }
1076
1077 return -1;
1078}
1079
1087static int get_desttype(const std::string & arg, FFMPEGFS_FORMAT_ARR & format)
1088{
1089 size_t pos = arg.find('=');
1090
1091 if (pos != std::string::npos)
1092 {
1093 std::string param(arg.substr(0, pos));
1094 std::vector<std::string> results = split(arg.substr(pos + 1), "\\+");
1095
1096 if (results.size() > 0 && results.size() < 3)
1097 {
1098 // Check for valid destination type and obtain codecs and file type.
1099 if (!format[0].init(results[0]))
1100 {
1101 std::fprintf(stderr, "INVALID PARAMETER (%s): No codecs available for desttype: %s\n", param.c_str(), results[0].c_str());
1102 return 1;
1103 }
1104
1105 if (results.size() == 2)
1106 {
1107 if (format[0].video_codec() == AV_CODEC_ID_NONE)
1108 {
1109 std::fprintf(stderr, "INVALID PARAMETER (%s): First format %s does not support video\n", param.c_str(), results[0].c_str());
1110 return 1;
1111 }
1112
1113 if (!format[1].init(results[1]))
1114 {
1115 std::fprintf(stderr, "INVALID PARAMETER (%s): No codecs available for desttype: %s\n", param.c_str(), results[1].c_str());
1116 return 1;
1117 }
1118
1119 if (format[1].video_codec() != AV_CODEC_ID_NONE)
1120 {
1121 std::fprintf(stderr, "INVALID PARAMETER (%s): Second format %s should be audio only\n", param.c_str(), results[1].c_str());
1122 return 1;
1123 }
1124 }
1125
1126 return 0;
1127 }
1128 }
1129
1130 std::fprintf(stderr, "INVALID PARAMETER (%s): Missing argument\n", arg.c_str());
1131
1132 return -1;
1133}
1134
1141static int get_audiocodec(const std::string & arg, AVCodecID *audio_codec)
1142{
1143 *audio_codec = AV_CODEC_ID_NONE;
1144
1145 size_t pos = arg.find('=');
1146
1147 if (pos != std::string::npos)
1148 {
1149 std::string param(arg.substr(0, pos));
1150 std::string data(arg.substr(pos + 1));
1151
1152 AUDIOCODEC_MAP::const_iterator it = audiocodec_map.find(data);
1153
1154 if (it == audiocodec_map.cend())
1155 {
1156 std::fprintf(stderr, "INVALID PARAMETER (%s): Invalid videocodec option: %s\n", param.c_str(), data.c_str());
1157
1158 list_options("Valid audio codecs", audiocodec_map);
1159
1160 return -1;
1161 }
1162
1163 *audio_codec = it->second;
1164
1165 return 0;
1166 }
1167
1168 std::fprintf(stderr, "INVALID PARAMETER (%s): Missing argument\n", arg.c_str());
1169
1170 return -1;
1171}
1172
1179static int get_videocodec(const std::string & arg, AVCodecID *video_codec)
1180{
1181 *video_codec = AV_CODEC_ID_NONE;
1182
1183 size_t pos = arg.find('=');
1184
1185 if (pos != std::string::npos)
1186 {
1187 std::string param(arg.substr(0, pos));
1188 std::string data(arg.substr(pos + 1));
1189
1190 VIDEOCODEC_MAP::const_iterator it = videocodec_map.find(data);
1191
1192 if (it == videocodec_map.cend())
1193 {
1194 std::fprintf(stderr, "INVALID PARAMETER (%s): Invalid videocodec option: %s\n", param.c_str(), data.c_str());
1195
1196 list_options("Valid video codecs", videocodec_map);
1197
1198 return -1;
1199 }
1200
1201 *video_codec = it->second;
1202
1203 return 0;
1204 }
1205
1206 std::fprintf(stderr, "INVALID PARAMETER (%s): Missing argument\n", arg.c_str());
1207
1208 return -1;
1209}
1210
1217static int get_autocopy(const std::string & arg, AUTOCOPY *autocopy)
1218{
1219 size_t pos = arg.find('=');
1220
1221 if (pos != std::string::npos)
1222 {
1223 std::string param(arg.substr(0, pos));
1224 std::string data(arg.substr(pos + 1));
1225
1226 AUTOCOPY_MAP::const_iterator it = autocopy_map.find(data);
1227
1228 if (it == autocopy_map.cend())
1229 {
1230 std::fprintf(stderr, "INVALID PARAMETER (%s): Invalid autocopy option: %s\n", param.c_str(), data.c_str());
1231
1232 list_options("Valid autocopy options are", autocopy_map);
1233
1234 return -1;
1235 }
1236
1237 *autocopy = it->second;
1238
1239 return 0;
1240 }
1241
1242 std::fprintf(stderr, "INVALID PARAMETER (%s): Missing argument\n", arg.c_str());
1243
1244 return -1;
1245}
1246
1247std::string get_audio_codec_text(AVCodecID audio_codec)
1248{
1249 AUDIOCODEC_MAP::const_iterator it = search_by_value(audiocodec_map, audio_codec);
1250 if (it != audiocodec_map.cend())
1251 {
1252 return it->first;
1253 }
1254 return "INVALID";
1255}
1256
1257std::string get_video_codec_text(AVCodecID video_codec)
1258{
1259 AUDIOCODEC_MAP::const_iterator it = search_by_value(videocodec_map, video_codec);
1260 if (it != videocodec_map.cend())
1261 {
1262 return it->first;
1263 }
1264 return "INVALID";
1265}
1266
1267std::string get_autocopy_text(AUTOCOPY autocopy)
1268{
1269 AUTOCOPY_MAP::const_iterator it = search_by_value(autocopy_map, autocopy);
1270 if (it != autocopy_map.cend())
1271 {
1272 return it->first;
1273 }
1274 return "INVALID";
1275}
1276
1283static int get_recodesame(const std::string & arg, RECODESAME *recode)
1284{
1285 size_t pos = arg.find('=');
1286
1287 if (pos != std::string::npos)
1288 {
1289 std::string param(arg.substr(0, pos));
1290 std::string data(arg.substr(pos + 1));
1291
1292 RECODESAME_MAP::const_iterator it = recode_map.find(data);
1293
1294 if (it == recode_map.cend())
1295 {
1296 std::fprintf(stderr, "INVALID PARAMETER (%s): Invalid recode option: %s\n", param.c_str(), data.c_str());
1297
1298 list_options("Valid recode options are", recode_map);
1299
1300 return -1;
1301 }
1302
1303 *recode = it->second;
1304
1305 return 0;
1306 }
1307
1308 std::fprintf(stderr, "INVALID PARAMETER (%s): Missing argument\n", arg.c_str());
1309
1310 return -1;
1311}
1312
1314{
1315 RECODESAME_MAP::const_iterator it = search_by_value(recode_map, recode);
1316 if (it != recode_map.cend())
1317 {
1318 return it->first;
1319 }
1320 return "INVALID";
1321}
1322
1329static int get_profile(const std::string & arg, PROFILE *profile)
1330{
1331 size_t pos = arg.find('=');
1332
1333 if (pos != std::string::npos)
1334 {
1335 std::string param(arg.substr(0, pos));
1336 std::string data(arg.substr(pos + 1));
1337
1338 PROFILE_MAP::const_iterator it = profile_map.find(data);
1339
1340 if (it == profile_map.cend())
1341 {
1342 std::fprintf(stderr, "INVALID PARAMETER (%s): Invalid profile: %s\n", param.c_str(), data.c_str());
1343
1344 list_options("Valid profiles are", profile_map);
1345
1346 return -1;
1347 }
1348
1349 *profile = it->second;
1350
1351 return 0;
1352 }
1353
1354 std::fprintf(stderr, "INVALID PARAMETER (%s): Missing argument\n", arg.c_str());
1355
1356 return -1;
1357}
1358
1359std::string get_profile_text(PROFILE profile)
1360{
1361 PROFILE_MAP::const_iterator it = search_by_value(profile_map, profile);
1362 if (it != profile_map.cend())
1363 {
1364 return it->first;
1365 }
1366 return "INVALID";
1367}
1368
1369// Read level
1376static int get_level(const std::string & arg, PRORESLEVEL *level)
1377{
1378 size_t pos = arg.find('=');
1379
1380 if (pos != std::string::npos)
1381 {
1382 std::string param(arg.substr(0, pos));
1383 std::string data(arg.substr(pos + 1));
1384
1385 LEVEL_MAP::const_iterator it = prores_level_map.find(data);
1386
1387 if (it == prores_level_map.cend())
1388 {
1389 std::fprintf(stderr, "INVALID PARAMETER (%s): Invalid level: %s\n", param.c_str(), data.c_str());
1390
1391 list_options("Valid levels are", prores_level_map);
1392
1393 return -1;
1394 }
1395
1396 *level = it->second;
1397
1398 return 0;
1399 }
1400
1401 std::fprintf(stderr, "INVALID PARAMETER (%s): Missing argument\n", arg.c_str());
1402
1403 return -1;
1404}
1405
1406// Get level text
1407std::string get_level_text(PRORESLEVEL level)
1408{
1409 LEVEL_MAP::const_iterator it = search_by_value(prores_level_map, level);
1410 if (it != prores_level_map.cend())
1411 {
1412 return it->first;
1413 }
1414 return "INVALID";
1415}
1416
1423static int get_segment_duration(const std::string & arg, int64_t *value)
1424{
1425 double duration;
1426 if (get_value(arg, &duration) < 0)
1427 {
1428 return -1;
1429 }
1430
1431 if (*value <= 0)
1432 {
1433 std::fprintf(stderr, "INVALID PARAMETER: segment_duration %.1f is out of range. For obvious reasons this must be greater than zero.\n", duration);
1434 return -1;
1435 }
1436
1437 *value = static_cast<int>(duration * AV_TIME_BASE);
1438
1439 return 0;
1440}
1441
1448static int get_seek_time_diff(const std::string & arg, int64_t *value)
1449{
1450 double duration;
1451 if (get_value(arg, &duration) < 0)
1452 {
1453 return -1;
1454 }
1455
1456 if (*value <= 0)
1457 {
1458 std::fprintf(stderr, "INVALID PARAMETER: seek time %.1f is out of range. For obvious reasons this must be greater than or equal zero.\n", duration);
1459 return -1;
1460 }
1461
1462 *value = static_cast<int>(duration * AV_TIME_BASE);
1463
1464 return 0;
1465}
1466
1476static int get_hwaccel(const std::string & arg, HWACCELAPI *hwaccel_API, AVHWDeviceType *hwaccel_device_type)
1477{
1478 size_t pos = arg.find('=');
1479
1480 if (pos != std::string::npos)
1481 {
1482 std::string param(arg.substr(0, pos));
1483 std::string data(arg.substr(pos + 1));
1484
1485 HWACCEL_MAP::const_iterator it = hwaccel_map.find(data);
1486
1487 if (it == hwaccel_map.cend())
1488 {
1489 std::fprintf(stderr, "INVALID PARAMETER (%s): Invalid hardware acceleration API: %s\n", param.c_str(), data.c_str());
1490
1491 list_options("Valid hardware acceleration APIs are", hwaccel_map);
1492
1493 return -1;
1494 }
1495
1496 const HWACCEL & hwaccel = it->second;
1497
1498 if (!hwaccel.m_supported)
1499 {
1500 std::fprintf(stderr, "INVALID PARAMETER (%s): Unsupported hardware acceleration API: %s\n", param.c_str(), data.c_str());
1501 return -1;
1502 }
1503
1504 *hwaccel_API = hwaccel.m_hwaccel_API;
1505 *hwaccel_device_type = hwaccel.m_hwaccel_device_type;
1506 return 0;
1507 }
1508
1509 std::fprintf(stderr, "INVALID PARAMETER (%s): Missing argument\n", arg.c_str());
1510
1511 return -1;
1512}
1513
1520static int get_codec(const std::string & codec, AVCodecID *codec_id)
1521{
1522 CODEC_MAP::const_iterator it = hwaccel_codec_map.find(codec);
1523
1524 if (it == hwaccel_codec_map.cend())
1525 {
1526 std::fprintf(stderr, "INVALID PARAMETER: Unknown codec '%s'.\n", codec.c_str());
1527
1528 list_options("Valid hardware acceleration APIs are", hwaccel_codec_map);
1529
1530 *codec_id = AV_CODEC_ID_NONE;
1531 return -1;
1532 }
1533
1534 *codec_id = it->second;
1535
1536 return 0;
1537}
1538
1545static int get_hwaccel_dec_blocked(const std::string & arg, HWACCEL_BLOCKED_MAP **hwaccel_dec_blocked)
1546{
1547 size_t pos = arg.find('=');
1548
1549 if (pos != std::string::npos)
1550 {
1551 std::string param(arg.substr(0, pos));
1552 std::stringstream data(arg.substr(pos + 1));
1553 std::string codec;
1554
1555 if (*hwaccel_dec_blocked == nullptr)
1556 {
1557 *hwaccel_dec_blocked = new (std::nothrow) HWACCEL_BLOCKED_MAP;
1558 }
1559
1560 if (!std::getline(data, codec, ':'))
1561 {
1562 std::fprintf(stderr, "INVALID PARAMETER (%s): Missing argument\n", param.c_str());
1563 return -1;
1564 }
1565
1566 AVCodecID codec_id;
1567
1568 if (get_codec(codec, &codec_id))
1569 {
1570 std::fprintf(stderr, "INVALID PARAMETER (%s): Unknown codec '%s'\n", param.c_str(), codec.c_str());
1571 return -1;
1572 }
1573
1574 int nProfilesFound = 0;
1575 for (std::string profile; std::getline(data, profile, ':');)
1576 {
1577 nProfilesFound++;
1578 // Block codec and profile
1579 (*hwaccel_dec_blocked)->insert(std::pair<AVCodecID, int>(codec_id, std::stoi(profile)));
1580 }
1581
1582 if (!nProfilesFound)
1583 {
1584 // No profile
1585 (*hwaccel_dec_blocked)->insert(std::pair<AVCodecID, int>(codec_id, AV_PROFILE_UNKNOWN));
1586 }
1587
1588 return 0;
1589 }
1590
1591 std::fprintf(stderr, "INVALID PARAMETER (%s): Missing argument\n", arg.c_str());
1592
1593 return -1;
1594}
1595
1596bool check_hwaccel_dec_blocked(AVCodecID codec_id, int profile)
1597{
1598 if (params.m_hwaccel_dec_blocked == nullptr)
1599 {
1600 return false; // Nothing blocked
1601 }
1602
1603 for (HWACCEL_BLOCKED_MAP::const_iterator it = params.m_hwaccel_dec_blocked->find(codec_id); it != params.m_hwaccel_dec_blocked->cend(); ++it)
1604 {
1605 if (it->first == codec_id && (it->second == profile || it->second == AV_PROFILE_UNKNOWN))
1606 {
1607 return true;
1608 }
1609 }
1610
1611 return false;
1612}
1613
1614std::string get_hwaccel_API_text(HWACCELAPI hwaccel_API)
1615{
1616 HWACCEL_MAP::const_iterator it = hwaccel_map.cbegin();
1617 while (it != hwaccel_map.cend())
1618 {
1619 if (it->second.m_hwaccel_API == hwaccel_API)
1620 {
1621 return it->first;
1622 }
1623 ++it;
1624 }
1625
1626 return "INVALID";
1627}
1628
1636static int get_value(const std::string & arg, int *value)
1637{
1638 size_t pos = arg.find('=');
1639
1640 if (pos != std::string::npos)
1641 {
1642 *value = std::stoi(arg.substr(pos + 1));
1643
1644 return 0;
1645 }
1646
1647 std::fprintf(stderr, "INVALID PARAMETER (%s): Missing argument\n", arg.c_str());
1648
1649 return -1;
1650}
1651
1659static int get_value(const std::string & arg, std::string *value)
1660{
1661 size_t pos = arg.find('=');
1662
1663 if (pos != std::string::npos)
1664 {
1665 *value = arg.substr(pos + 1);
1666
1667 return 0;
1668 }
1669
1670 std::fprintf(stderr, "INVALID PARAMETER (%s): Missing argument\n", arg.c_str());
1671
1672 return -1;
1673}
1674
1682static int get_value(const std::string & arg, MATCHVEC *value)
1683{
1684 size_t pos = arg.find('=');
1685
1686 if (pos != std::string::npos)
1687 {
1688 std::vector<std::string> v = split(arg.substr(pos + 1), ",");
1689
1690 for (const std::string & str : v)
1691 {
1692 int res = fnmatch(str.c_str(), "", 0);
1693
1694 if (res != 0 && res != FNM_NOMATCH)
1695 {
1696 std::fprintf(stderr, "INVALID PARAMETER (%s): Error in wildcard pattern\n", str.c_str());
1697
1698 return -1;
1699 }
1700 }
1701
1702 value->insert(value->end(), v.begin(), v.end());
1703
1704 return 0;
1705 }
1706
1707 std::fprintf(stderr, "INVALID PARAMETER (%s): Missing argument\n", arg.c_str());
1708
1709 return -1;
1710}
1711
1712#if 0
1720static int get_value(const std::string & arg, std::optional<std::string> *value)
1721{
1722 size_t pos = arg.find('=');
1723
1724 if (pos != std::string::npos)
1725 {
1726 *value = arg.substr(pos + 1);
1727
1728 return 0;
1729 }
1730
1731 std::fprintf(stderr, "INVALID PARAMETER (%s): Missing argument\n", arg.c_str());
1732
1733 return -1;
1734}
1735#endif
1736
1744static int get_value(const std::string & arg, double *value)
1745{
1746 size_t pos = arg.find('=');
1747
1748 if (pos != std::string::npos)
1749 {
1750 *value = std::stof(arg.substr(pos + 1));
1751
1752 return 0;
1753 }
1754
1755 std::fprintf(stderr, "INVALID PARAMETER (%s): Missing argument\n", arg.c_str());
1756
1757 return -1;
1758}
1759
1768static int ffmpegfs_opt_proc(__attribute__((unused)) void* data, const char* arg, int key, struct fuse_args *outargs)
1769{
1770 switch (key)
1771 {
1772 case FUSE_OPT_KEY_NONOPT:
1773 {
1774 static int n;
1775
1776 // check for basepath and bitrate parameters
1777 if (n == 0 && params.m_basepath.empty())
1778 {
1782 n++;
1783 return 0;
1784 }
1785 else if (n == 1 && params.m_mountpath.empty())
1786 {
1790 if (!docker_client)
1791 {
1792 switch (is_mount(params.m_mountpath))
1793 {
1794 case 1:
1795 {
1796 std::fprintf(stderr, "%-25s: already mounted\n", params.m_mountpath.c_str());
1797 exit(1);
1798 }
1799 //case -1:
1800 //{
1801 // // Error already reported
1802 // exit(1);
1803 //}
1804 }
1805 }
1806
1807 n++;
1808 return 1;
1809 }
1810
1811 break;
1812 }
1813 case KEY_HELP:
1814 {
1815 usage();
1816 fuse_opt_add_arg(outargs, "-ho");
1817 fuse_main(outargs->argc, outargs->argv, &ffmpegfs_ops, nullptr);
1818 exit(1);
1819 }
1820 case KEY_VERSION:
1821 {
1822 std::printf("-------------------------------------------------------------------------------------------\n");
1823
1824#ifdef __GNUC__
1825#ifndef __clang_version__
1826 std::printf("%-20s: %s (%s)\n", "Built with", "gcc " __VERSION__, HOST_OS);
1827#else
1828 std::printf("%-20s: %s (%s)\n", "Built with", "clang " __clang_version__, HOST_OS);
1829#endif
1830#endif
1831 std::printf("%-20s: %s\n\n", "configuration", CONFIGURE_ARGS);
1832
1833 std::printf("%-20s: %s\n", PACKAGE_NAME " Version", FFMPEFS_VERSION);
1834
1835 std::printf("%s", ffmpeg_libinfo().c_str());
1836
1837#ifdef USE_LIBVCD
1838 std::printf("%-20s: %s\n", "Video CD Library", "enabled");
1839#endif // USE_LIBVCD
1840#ifdef USE_LIBDVD
1841 std::printf("%-20s: %s\n", "DVD Library", "enabled");
1842#endif // USE_LIBDVD
1843#ifdef USE_LIBBLURAY
1844 std::printf("%-20s: %s\n", "Blu-ray Library", BLURAY_VERSION_STRING);
1845#endif // USE_LIBBLURAY
1846
1847 fuse_opt_add_arg(outargs, "--version");
1848 fuse_main(outargs->argc, outargs->argv, &ffmpegfs_ops, nullptr);
1849
1850 exit(0);
1851 }
1852 case KEY_FFMPEG_CAPS:
1853 {
1854 std::printf("-------------------------------------------------------------------------------------------\n\n");
1855
1856 std::printf("%-20s: %s\n", PACKAGE_NAME " Version", FFMPEFS_VERSION);
1857 std::printf("%s", ffmpeg_libinfo().c_str());
1858
1859 std::printf("\nFFMpeg Capabilities\n\n");
1860
1861 show_caps(0);
1862
1863 exit(0);
1864 }
1865 case KEY_DESTTYPE:
1866 {
1867 return get_desttype(arg, ffmpeg_format);
1868 }
1869 case KEY_AUDIOCODEC:
1870 {
1871 return get_audiocodec(arg, &params.m_audio_codec);
1872 }
1873 case KEY_VIDEOCODEC:
1874 {
1875 return get_videocodec(arg, &params.m_video_codec);
1876 }
1877 case KEY_AUTOCOPY:
1878 {
1879 return get_autocopy(arg, &params.m_autocopy);
1880 }
1881 case KEY_RECODESAME:
1882 {
1883 return get_recodesame(arg, &params.m_recodesame);
1884 }
1885 case KEY_PROFILE:
1886 {
1887 return get_profile(arg, &params.m_profile);
1888 }
1889 case KEY_LEVEL:
1890 {
1891 return get_level(arg, &params.m_level);
1892 }
1893 case KEY_AUDIO_BITRATE:
1894 {
1895 return get_bitrate(arg, &params.m_audiobitrate);
1896 }
1897 case KEY_AUDIO_SAMPLERATE:
1898 {
1900 }
1901 case KEY_AUDIO_CHANNELS:
1902 {
1903 return get_value(arg, &params.m_audiochannels);
1904 }
1905 case KEY_AUDIO_SAMPLE_FMT:
1906 {
1907 return get_sampleformat(arg, &params.m_sample_fmt);
1908 }
1909 case KEY_SCRIPTFILE:
1910 {
1911 return get_value(arg, &params.m_scriptfile);
1912 }
1913 case KEY_SCRIPTSOURCE:
1914 {
1915 return get_value(arg, &params.m_scriptsource);
1916 }
1917 case KEY_VIDEO_BITRATE:
1918 {
1919 return get_bitrate(arg, &params.m_videobitrate);
1920 }
1921 case KEY_SEGMENT_DURATION:
1922 {
1924 }
1925 case KEY_MIN_SEEK_TIME_DIFF:
1926 {
1928 }
1929 case KEY_HWACCEL_ENCODER_API:
1930 {
1932 }
1933 case KEY_HWACCEL_ENCODER_DEVICE:
1934 {
1936 }
1937 case KEY_HWACCEL_DECODER_API:
1938 {
1940 }
1941 case KEY_HWACCEL_DECODER_DEVICE:
1942 {
1944 }
1945 case KEY_HWACCEL_DECODER_BLOCKED:
1946 {
1948 }
1949 case KEY_EXPIRY_TIME:
1950 {
1951 return get_time(arg, &params.m_expiry_time);
1952 }
1953 case KEY_MAX_INACTIVE_SUSPEND_TIME:
1954 {
1956 }
1957 case KEY_MAX_INACTIVE_ABORT_TIME:
1958 {
1959 return get_time(arg, &params.m_max_inactive_abort);
1960 }
1961 case KEY_PREBUFFER_TIME:
1962 {
1963 return get_time(arg, &params.m_prebuffer_time);
1964 }
1965 case KEY_PREBUFFER_SIZE:
1966 {
1967 return get_size(arg, &params.m_prebuffer_size);
1968 }
1969 case KEY_MAX_CACHE_SIZE:
1970 {
1971 return get_size(arg, &params.m_max_cache_size);
1972 }
1973 case KEY_MIN_DISKSPACE_SIZE:
1974 {
1975 return get_size(arg, &params.m_min_diskspace);
1976 }
1977 case KEY_CACHEPATH:
1978 {
1979 return get_value(arg, &params.m_cachepath);
1980 }
1981 case KEY_CACHE_MAINTENANCE:
1982 {
1983 return get_time(arg, &params.m_cache_maintenance);
1984 }
1985 case KEY_LOG_MAXLEVEL:
1986 {
1987 return get_value(arg, &params.m_log_maxlevel);
1988 }
1989 case KEY_LOGFILE:
1990 {
1991 std::string logfile;
1992 int res = get_value(arg, &logfile);
1993
1994 if (res)
1995 {
1996 return res;
1997 }
1998
1999 expand_path(&params.m_logfile, logfile);
2001
2002 return 0;
2003 }
2004 case KEY_INCLUDE_EXTENSIONS:
2005 {
2006 return get_value(arg, params.m_include_extensions.get());
2007 }
2008 case KEY_HIDE_EXTENSIONS:
2009 {
2010 return get_value(arg, params.m_hide_extensions.get());
2011 }
2012 }
2013
2014 return 1;
2015}
2016
2021static bool set_defaults()
2022{
2023 if (ffmpeg_format[FORMAT::VIDEO].video_codec() == AV_CODEC_ID_PRORES)
2024 {
2026 {
2028 }
2029 }
2030
2031 return true;
2032}
2033
2040{
2041 for (AVHWDeviceType device_type = AV_HWDEVICE_TYPE_NONE; (device_type = av_hwdevice_iterate_types(device_type)) != AV_HWDEVICE_TYPE_NONE;)
2042 {
2043 HWACCEL_MAP::iterator it = hwaccel_map.find(av_hwdevice_get_type_name(device_type));
2044
2045 if (it == hwaccel_map.end())
2046 {
2047 continue;
2048 }
2049
2050 it->second.m_hwaccel_device_type = device_type;
2051 }
2052}
2053
2063const char *value_or_none(const char *value)
2064{
2065 return (value != nullptr ? value : "NONE");
2066}
2067
2071static void print_params()
2072{
2073 std::string cachepath;
2074
2075 transcoder_cache_path(&cachepath);
2076
2077 Logging::trace(nullptr, "********* " PACKAGE_NAME " Options *********");
2078 Logging::trace(nullptr, "Base Path : %1", params.m_basepath.c_str());
2079 Logging::trace(nullptr, "Mount Path : %1", params.m_mountpath.c_str());
2080 Logging::trace(nullptr, "--------- Format ---------");
2081 if (ffmpeg_format[FORMAT::AUDIO].filetype() != FILETYPE::UNKNOWN)
2082 {
2083 Logging::trace(nullptr, "Audio File Type : %1", ffmpeg_format[FORMAT::AUDIO].desttype().c_str());
2084 if (ffmpeg_format[FORMAT::AUDIO].audio_codec() != AV_CODEC_ID_NONE)
2085 {
2086 Logging::trace(nullptr, "Audio Codec : %1 (%2)", get_codec_name(ffmpeg_format[FORMAT::AUDIO].audio_codec(), false), get_codec_name(ffmpeg_format[FORMAT::AUDIO].audio_codec(), true));
2087 }
2088 Logging::trace(nullptr, "Video File Type : %1", ffmpeg_format[FORMAT::VIDEO].desttype().c_str());
2089 if (ffmpeg_format[FORMAT::VIDEO].audio_codec() != AV_CODEC_ID_NONE)
2090 {
2091 Logging::trace(nullptr, "Audio Codec : %1 (%2)", get_codec_name(ffmpeg_format[FORMAT::VIDEO].audio_codec(), false), get_codec_name(ffmpeg_format[FORMAT::VIDEO].audio_codec(), true));
2092 }
2093 if (ffmpeg_format[FORMAT::VIDEO].video_codec() != AV_CODEC_ID_NONE)
2094 {
2095 Logging::trace(nullptr, "Video Codec : %1 (%2)", get_codec_name(ffmpeg_format[FORMAT::VIDEO].video_codec(), false), get_codec_name(ffmpeg_format[FORMAT::VIDEO].video_codec(), true));
2096 }
2097 }
2098 else
2099 {
2100 Logging::trace(nullptr, "File Type : %1", ffmpeg_format[FORMAT::VIDEO].desttype().c_str());
2101 if (ffmpeg_format[FORMAT::VIDEO].audio_codec() != AV_CODEC_ID_NONE)
2102 {
2103 Logging::trace(nullptr, "Audio Codec : %1 (%2)", get_codec_name(ffmpeg_format[FORMAT::VIDEO].audio_codec(), false), get_codec_name(ffmpeg_format[FORMAT::VIDEO].audio_codec(), true));
2104 }
2105 if (ffmpeg_format[FORMAT::VIDEO].video_codec() != AV_CODEC_ID_NONE)
2106 {
2107 Logging::trace(nullptr, "Video Codec : %1 (%2)", get_codec_name(ffmpeg_format[FORMAT::VIDEO].video_codec(), false), get_codec_name(ffmpeg_format[FORMAT::VIDEO].video_codec(), true));
2108 }
2109 }
2110 Logging::trace(nullptr, "Smart Transcode : %1", params.smart_transcode() ? "yes" : "no");
2111 Logging::trace(nullptr, "Auto Copy : %1", get_autocopy_text(params.m_autocopy).c_str());
2112 Logging::trace(nullptr, "Recode to same fmt: %1", get_recodesame_text(params.m_recodesame).c_str());
2113 Logging::trace(nullptr, "Profile : %1", get_profile_text(params.m_profile).c_str());
2114 Logging::trace(nullptr, "Level : %1", get_level_text(params.m_level).c_str());
2115 Logging::trace(nullptr, "Include Extensions: %1", implode(*params.m_include_extensions).c_str());
2116 Logging::trace(nullptr, "Hide Extensions : %1", implode(*params.m_hide_extensions).c_str());
2117 Logging::trace(nullptr, "--------- Audio ---------");
2118 Logging::trace(nullptr, "Codecs : %1+%2", get_codec_name(ffmpeg_format[FORMAT::VIDEO].audio_codec(), true), get_codec_name(ffmpeg_format[FORMAT::AUDIO].audio_codec(), true));
2119 Logging::trace(nullptr, "Bitrate : %1", format_bitrate(params.m_audiobitrate).c_str());
2120 Logging::trace(nullptr, "Sample Rate : %1", format_samplerate(params.m_audiosamplerate).c_str());
2121 Logging::trace(nullptr, "Max. Channels : %1", params.m_audiochannels);
2123 {
2124 Logging::trace(nullptr, "Sample Format : %1", get_sampleformat_text(params.m_sample_fmt).c_str());
2125 }
2126 Logging::trace(nullptr, "--------- Video ---------");
2127 Logging::trace(nullptr, "Codec : %1", get_codec_name(ffmpeg_format[FORMAT::VIDEO].video_codec(), true));
2128 Logging::trace(nullptr, "Bitrate : %1", format_bitrate(params.m_videobitrate).c_str());
2129 Logging::trace(nullptr, "Dimension : width=%1 height=%2", format_number(params.m_videowidth).c_str(), format_number(params.m_videoheight).c_str());
2130 Logging::trace(nullptr, "Deinterlace : %1", params.m_deinterlace ? "yes" : "no");
2131 Logging::trace(nullptr, "--------- HLS Options ---------");
2132 Logging::trace(nullptr, "Segment Duration : %1", format_time(static_cast<time_t>(params.m_segment_duration / AV_TIME_BASE)).c_str());
2133 Logging::trace(nullptr, "Seek Time Diff : %1", format_time(static_cast<time_t>(params.m_min_seek_time_diff / AV_TIME_BASE)).c_str());
2134 Logging::trace(nullptr, "---- Hardware Acceleration ----");
2135 Logging::trace(nullptr, "Hardware Decoder:");
2136 Logging::trace(nullptr, "API : %1", get_hwaccel_API_text(params.m_hwaccel_dec_API).c_str());
2137 Logging::trace(nullptr, "Frame Buffering : %1", value_or_none(av_hwdevice_get_type_name(params.m_hwaccel_dec_device_type)));
2138 Logging::trace(nullptr, "Device : %1", params.m_hwaccel_dec_device.c_str());
2139 Logging::trace(nullptr, "Hardware Encoder:");
2140 Logging::trace(nullptr, "API : %1", get_hwaccel_API_text(params.m_hwaccel_enc_API).c_str());
2141 Logging::trace(nullptr, "Frame Buffering : %1", value_or_none(av_hwdevice_get_type_name(params.m_hwaccel_enc_device_type)));
2142 Logging::trace(nullptr, "Device : %1", params.m_hwaccel_enc_device.c_str());
2143 Logging::trace(nullptr, "--------- Subtitles ---------");
2144 Logging::trace(nullptr, "No subtitles : %1", params.m_no_subtitles ? "yes" : "no");
2145 Logging::trace(nullptr, "--------- Virtual Script ---------");
2146 Logging::trace(nullptr, "Create script : %1", params.m_enablescript ? "yes" : "no");
2147 Logging::trace(nullptr, "Script file name : %1", params.m_scriptfile.c_str());
2148 Logging::trace(nullptr, "Input file : %1", params.m_scriptsource.c_str());
2149 Logging::trace(nullptr, "--------- Logging ---------");
2150 Logging::trace(nullptr, "Max. Log Level : %1", params.m_log_maxlevel.c_str());
2151 Logging::trace(nullptr, "Log to stderr : %1", params.m_log_stderr ? "yes" : "no");
2152 Logging::trace(nullptr, "Log to syslog : %1", params.m_log_syslog ? "yes" : "no");
2153 Logging::trace(nullptr, "Logfile : %1", !params.m_logfile.empty() ? params.m_logfile.c_str() : "none");
2154 Logging::trace(nullptr, "--------- Cache Settings ---------");
2155 Logging::trace(nullptr, "Expiry Time : %1", format_time(params.m_expiry_time).c_str());
2156 Logging::trace(nullptr, "Inactivity Suspend: %1", format_time(params.m_max_inactive_suspend).c_str());
2157 Logging::trace(nullptr, "Inactivity Abort : %1", format_time(params.m_max_inactive_abort).c_str());
2158 Logging::trace(nullptr, "Pre-buffer Time : %1", format_time(params.m_prebuffer_time).c_str());
2159 Logging::trace(nullptr, "Pre-buffer Size : %1", format_size(params.m_prebuffer_size).c_str());
2160 Logging::trace(nullptr, "Max. Cache Size : %1", format_size(params.m_max_cache_size).c_str());
2161 Logging::trace(nullptr, "Min. Disk Space : %1", format_size(params.m_min_diskspace).c_str());
2162 Logging::trace(nullptr, "Cache Path : %1", cachepath.c_str());
2163 Logging::trace(nullptr, "Disable Cache : %1", params.m_disable_cache ? "yes" : "no");
2164 Logging::trace(nullptr, "Maintenance Timer : %1", params.m_cache_maintenance ? format_time(params.m_cache_maintenance).c_str() : "inactive");
2165 Logging::trace(nullptr, "Clear Cache : %1", params.m_clear_cache ? "yes" : "no");
2166 Logging::trace(nullptr, "--------- Various Options ---------");
2167 Logging::trace(nullptr, "Remove Album Arts : %1", params.m_noalbumarts ? "yes" : "no");
2168 Logging::trace(nullptr, "Max. Threads : %1", format_number(params.m_max_threads).c_str());
2169 Logging::trace(nullptr, "Decoding Errors : %1", params.m_decoding_errors ? "break transcode" : "ignore");
2170 Logging::trace(nullptr, "Min. DVD Chapter : %1", format_duration(params.m_min_dvd_chapter_duration * AV_TIME_BASE).c_str());
2171 Logging::trace(nullptr, "Old Name Scheme : %1", params.m_oldnamescheme ? "yes" : "no");
2172 Logging::trace(nullptr, "--------- Experimental Options ---------");
2173 Logging::trace(nullptr, "Windows 10 Fix : %1", params.m_win_smb_fix ? "SMB Lockup Fix Active" : "inactive");
2174}
2175
2183static void ffmpeg_log(void *ptr, int level, const char *fmt, va_list vl)
2184{
2185 Logging::LOGLEVEL ffmpegfs_level;
2186
2187 // Map log level
2188 // AV_LOG_PANIC 0
2189 // AV_LOG_FATAL 8
2190 // AV_LOG_ERROR 16
2191 if (level <= AV_LOG_ERROR)
2192 {
2193 ffmpegfs_level = LOGERROR;
2194 }
2195 // AV_LOG_WARNING 24
2196 else if (level <= AV_LOG_WARNING)
2197 {
2198 ffmpegfs_level = LOGWARN;
2199 }
2200#ifdef AV_LOG_TRACE
2201 // AV_LOG_INFO 32
2202 //else if (level <= AV_LOG_INFO)
2203 //{
2204 // ffmpegfs_level = LOGINFO;
2205 //}
2206 // AV_LOG_VERBOSE 40
2207 // AV_LOG_DEBUG 48
2208 else if (level < AV_LOG_DEBUG)
2209 {
2210 ffmpegfs_level = LOGDEBUG;
2211 }
2212 // AV_LOG_TRACE 56
2213 else // if (level <= AV_LOG_TRACE)
2214 {
2215 ffmpegfs_level = LOGTRACE;
2216 }
2217#else
2218 // AV_LOG_INFO 32
2219 else // if (level <= AV_LOG_INFO)
2220 {
2221 ffmpegfs_level = DEBUG;
2222 }
2223#endif
2224
2225 if (!Logging::show(ffmpegfs_level))
2226 {
2227 return;
2228 }
2229
2230 va_list vl2;
2231 static int print_prefix = 1;
2232
2233#if (LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 23, 0))
2234 char * line;
2235 int line_size;
2236 std::string category;
2237
2238 if (ptr != nullptr)
2239 {
2240 AVClass* avc = *(AVClass **)ptr;
2241
2242 switch (avc->category)
2243 {
2244 case AV_CLASS_CATEGORY_NA:
2245 {
2246 break;
2247 }
2248 case AV_CLASS_CATEGORY_INPUT:
2249 {
2250 category = "INPUT ";
2251 break;
2252 }
2253 case AV_CLASS_CATEGORY_OUTPUT:
2254 {
2255 category = "OUTPUT ";
2256 break;
2257 }
2258 case AV_CLASS_CATEGORY_MUXER:
2259 {
2260 category = "MUXER ";
2261 break;
2262 }
2263 case AV_CLASS_CATEGORY_DEMUXER:
2264 {
2265 category = "DEMUXER ";
2266 break;
2267 }
2268 case AV_CLASS_CATEGORY_ENCODER:
2269 {
2270 category = "ENCODER ";
2271 break;
2272 }
2273 case AV_CLASS_CATEGORY_DECODER:
2274 {
2275 category = "DECODER ";
2276 break;
2277 }
2278 case AV_CLASS_CATEGORY_FILTER:
2279 {
2280 category = "FILTER ";
2281 break;
2282 }
2283 case AV_CLASS_CATEGORY_BITSTREAM_FILTER:
2284 {
2285 category = "BITFILT ";
2286 break;
2287 }
2288 case AV_CLASS_CATEGORY_SWSCALER:
2289 {
2290 category = "SWSCALE ";
2291 break;
2292 }
2293 case AV_CLASS_CATEGORY_SWRESAMPLER:
2294 {
2295 category = "SWRESAM ";
2296 break;
2297 }
2298 default:
2299 {
2300 strsprintf(&category, "CAT %3i ", static_cast<int>(avc->category));
2301 break;
2302 }
2303 }
2304 }
2305
2306 va_copy(vl2, vl);
2307 av_log_default_callback(ptr, level, fmt, vl);
2308 line_size = av_log_format_line2(ptr, level, fmt, vl2, nullptr, 0, &print_prefix);
2309 if (line_size < 0)
2310 {
2311 va_end(vl2);
2312 return;
2313 }
2314 line = static_cast<char *>(av_malloc(static_cast<size_t>(line_size)));
2315 if (line == nullptr)
2316 {
2317 return;
2318 }
2319 av_log_format_line2(ptr, level, fmt, vl2, line, line_size, &print_prefix);
2320 va_end(vl2);
2321#else
2322 char line[1024];
2323
2324 va_copy(vl2, vl);
2325 av_log_default_callback(ptr, level, fmt, vl);
2326 av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix);
2327 va_end(vl2);
2328#endif
2329
2330 Logging::log_with_level(ffmpegfs_level, "", category + line);
2331
2332#if (LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 23, 0))
2333 av_free(line);
2334#endif
2335}
2336
2345static bool init_logging(const std::string &logfile, const std::string & max_level, bool to_stderr, bool to_syslog)
2346{
2347 static const std::map<const std::string, const Logging::LOGLEVEL, comp> log_level_map =
2348 {
2349 { "ERROR", LOGERROR },
2350 { "WARNING", LOGWARN },
2351 { "INFO", LOGINFO },
2352 { "DEBUG", LOGDEBUG },
2353 { "TRACE", LOGTRACE },
2354 };
2355
2356 std::map<const std::string, const Logging::LOGLEVEL, comp>::const_iterator it = log_level_map.find(max_level);
2357
2358 if (it == log_level_map.cend())
2359 {
2360 std::fprintf(stderr, "Invalid logging level string: %s\n", max_level.c_str());
2361 return false;
2362 }
2363
2364 return Logging::init_logging(logfile, it->second, to_stderr, to_syslog);
2365}
2366
2374int main(int argc, char *argv[])
2375{
2376 int ret;
2377
2378 struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
2379
2380 // Check if run from other process group like mount and if so, inhibit startup message
2381 if (getppid() == getpgid(0))
2382 {
2383 std::printf("%s V%s\n", PACKAGE_NAME, FFMPEFS_VERSION);
2384 std::printf("Copyright (C) 2017-2026 Norbert Schlia (nschlia@oblivion-software.de)\n"
2385 "David Collett (2006-2008) and K. Henriksson (2008-2012)\n\n");
2386 }
2387
2388 // Check if run under Docker
2390
2391 init_fuse_ops();
2392
2393 // Redirect FFmpeg logs
2394 av_log_set_callback(ffmpeg_log);
2395
2396 // Set default
2397 params.m_max_threads = static_cast<unsigned int>(get_nprocs() * 16);
2398
2399 // Build list of supported device types
2401
2402 if (fuse_opt_parse(&args, &params, ffmpegfs_opts, ffmpegfs_opt_proc))
2403 {
2404 std::fprintf(stderr, "\nError parsing command line options.\n\n");
2405 //usage(argv[0]);
2406 return 1;
2407 }
2408
2409 // Expand cache path
2410 if (!params.m_cachepath.empty())
2411 {
2414 }
2415
2416 // Log to the screen, and enable debug messages, if debug is enabled.
2417 if (params.m_debug)
2418 {
2419 params.m_log_stderr = 1;
2420 params.m_log_maxlevel = "DEBUG";
2421 av_log_set_level(AV_LOG_INFO); // Do not use AV_LOG_DEBUG; AV_LOG_INFO is chatty enough
2422 }
2423 else
2424 {
2425 av_log_set_level(AV_LOG_QUIET);
2426 }
2427
2429 {
2430 std::fprintf(stderr, "ERROR: Failed to initialise logging module.\n");
2431 std::fprintf(stderr, "Maybe log file couldn't be opened for writing?\n\n");
2432 return 1;
2433 }
2434
2436 {
2437 if (args.argc > 1)
2438 {
2439 std::fprintf(stderr, "INVALID PARAMETER: Invalid additional parameters for --prune_cache:\n");
2440 for (int n = 1; n < args.argc; n++)
2441 {
2442 std::fprintf(stderr, "Invalid: '%s'\n", args.argv[n]);
2443 }
2444 return 1;
2445 }
2446
2447 // Prune cache and exit
2448 if (!transcoder_init())
2449 {
2450 return 1;
2451 }
2453 return 0;
2454 }
2455
2456 if (params.m_basepath.empty())
2457 {
2458 std::fprintf(stderr, "INVALID PARAMETER: No valid basepath specified.\n\n");
2459 return 1;
2460 }
2461
2462 if (params.m_basepath.front() != '/')
2463 {
2464 std::fprintf(stderr, "INVALID PARAMETER: basepath must be an absolute path.\n\n");
2465 return 1;
2466 }
2467
2468 struct stat stbuf;
2469 if (stat(params.m_basepath.c_str(), &stbuf) != 0 || !S_ISDIR(stbuf.st_mode))
2470 {
2471 std::fprintf(stderr, "INVALID PARAMETER: basepath is not a valid directory: %s\n\n", params.m_basepath.c_str());
2472 return 1;
2473 }
2474
2475 if (params.m_mountpath.empty())
2476 {
2477 std::fprintf(stderr, "INVALID PARAMETER: No valid mountpath specified.\n\n");
2478 return 1;
2479 }
2480
2481 if (params.m_mountpath.front() != '/')
2482 {
2483 std::fprintf(stderr, "INVALID PARAMETER: mountpath must be an absolute path.\n\n");
2484 return 1;
2485 }
2486
2487 if (stat(params.m_mountpath.c_str(), &stbuf) != 0 || !S_ISDIR(stbuf.st_mode))
2488 {
2489 std::fprintf(stderr, "INVALID PARAMETER: mountpath is not a valid directory: %s\n\n", params.m_mountpath.c_str());
2490 return 1;
2491 }
2492
2493 // Check if sample format is supported
2494 for (const FFmpegfs_Format & fmt : ffmpeg_format)
2495 {
2496 if (fmt.filetype() != FILETYPE::UNKNOWN && !fmt.is_sample_fmt_supported())
2497 {
2498 std::fprintf(stderr, "INVALID PARAMETER: %s does not support the sample format %s\n\n", fmt.desttype().c_str(), get_sampleformat_text(params.m_sample_fmt).c_str());
2499 std::fprintf(stderr, "Supported formats: %s\n\n", fmt.sample_fmt_list().c_str());
2500 return 1;
2501 }
2502 }
2503
2504 // Check if audio or video codec is supported
2505 for (const FFmpegfs_Format & fmt : ffmpeg_format)
2506 {
2507 if (fmt.filetype() != FILETYPE::UNKNOWN)
2508 {
2509 if (params.m_audio_codec != AV_CODEC_ID_NONE && !fmt.is_audio_codec_supported(params.m_audio_codec))
2510 {
2511 std::fprintf(stderr, "INVALID PARAMETER: %s does not support audio codec %s\n\n", fmt.desttype().c_str(), get_audio_codec_text(params.m_audio_codec).c_str());
2512 std::fprintf(stderr, "Supported formats: %s\n\n", fmt.audio_codec_list().c_str());
2513 return 1;
2514 }
2515
2516 if (params.m_video_codec != AV_CODEC_ID_NONE && !fmt.is_video_codec_supported(params.m_video_codec))
2517 {
2518 std::fprintf(stderr, "INVALID PARAMETER: %s does not support video codec %s\n\n", fmt.desttype().c_str(), get_video_codec_text(params.m_video_codec).c_str());
2519 std::fprintf(stderr, "Supported formats: %s\n\n", fmt.video_codec_list().c_str());
2520 return 1;
2521 }
2522 }
2523 }
2524
2525 if (!set_defaults())
2526 {
2527 return 1;
2528 }
2529
2530 if (!transcoder_init())
2531 {
2532 return 1;
2533 }
2534
2535 print_params();
2536
2538 {
2539 // Prune cache and exit
2541 {
2542 return 1;
2543 }
2544 }
2545
2546 // start FUSE
2547 ret = fuse_main(args.argc, args.argv, &ffmpegfs_ops, nullptr);
2548
2549 fuse_opt_free_args(&args);
2550
2551 return ret;
2552}
@ NONE
No result code available.
The FFmpegfs_Format class.
static void log_with_level(LOGLEVEL loglevel, const char *filename, const std::string &message)
Write log entry.
Definition logging.cc:226
static bool init_logging(const std::string &logfile, LOGLEVEL max_level, bool to_stderr, bool to_syslog)
Initialise the logging facility.
Definition logging.cc:210
static void trace(const T filename, const std::string &format_string, Args &&...args)
Write trace level log entry.
Definition logging.h:163
static bool show(LOGLEVEL loglevel)
Check if log entry should be displayed at the current log level.
Definition logging.h:272
LOGLEVEL
Logging level types enum.
Definition logging.h:85
const char * get_codec_name(AVCodecID codec_id, bool long_name)
Safe way to get the codec name. Function never fails, will return "unknown" on error.
std::string format_duration(int64_t value, uint32_t fracs)
Format a time in format HH:MM:SS.fract.
int is_mount(const std::string &path)
Check if path is a mount.
std::string ffmpeg_libinfo()
Get info about the FFmpeg libraries used.
std::string sanitise_filepath(std::string *filepath)
Sanitise file name. Calls realpath() to remove duplicate // or resolve ../.. etc. Changes the path in...
int reg_compare(const std::string &value, const std::string &pattern, std::regex::flag_type flag)
Compare value with pattern.
int show_caps(int device_only)
Lists all supported codecs and devices.
std::string format_time(time_t value)
Format a time in format "w d m s".
std::string format_samplerate(int value)
Format a samplerate.
std::string format_bitrate(BITRATE value)
Format a bit rate.
bool detect_docker()
Detect if we are running under Docker.
const std::string & append_sep(std::string *path)
Add / to the path if required.
const std::string & expand_path(std::string *tgt, const std::string &src)
Expand path, e.g., expand ~/ to home directory.
std::string format_size(uint64_t value)
Format size.
std::vector< std::string > split(const std::string &input, const std::string &regex)
Split string into an array delimited by a regular expression.
std::string format_number(int64_t value)
Format numeric value.
PRORESLEVEL
@ PRORES_STANDARD
Prores Level: STANDARD.
@ NONE
No level.
@ PRORES_PROXY
Prores Level: PROXY.
@ PRORES_HQ
Prores Level: HQ.
@ PRORES_LT
Prores Level: LT.
std::array< FFmpegfs_Format, 2 > FFMPEGFS_FORMAT_ARR
Array of FFmpegfs formats. There are two, for audio and video.
RECODESAME
@ YES
Always recode to same format.
@ NO
Never recode to same format.
#define BITRATE
For FFmpeg bit rate is an int.
std::string implode(const T &s)
Combine array of strings into comma separated list.
PROFILE
@ MP4_MAXTHON
Maxthon.
@ MP4_CHROME
Google Chrome.
@ MP4_OPERA
Opera.
@ MP4_EDGE
MS Edge.
@ MP4_IE
MS Internet Explorer.
@ ALAC_ITUNES
Optimised for iTunes.
@ DEFAULT
No specific profile/Don't care.
@ MP4_SAFARI
Apple Safari.
@ MP4_FF
Firefox.
#define FFMPEFS_VERSION
FFmpegfs version number.
std::map< conststd::string, constT, comp >::const_iterator search_by_value(const std::map< const std::string, const T, comp > &mapOfWords, T value)
Iterate through all elements in map and search for the passed element.
AUTOCOPY
@ STRICT
Copy stream if codec matches desired target, transcode otherwise.
@ MATCH
Copy stream if target supports codec.
@ MATCHLIMIT
Same as MATCH, only copy if target not larger transcode otherwise.
@ OFF
Never copy streams, transcode always.
@ STRICTLIMIT
Same as STRICT, only copy if target not larger, transcode otherwise.
const std::string & strsprintf(std::string *str, const std::string &format, Args ... args)
Format a std::string sprintf-like.
std::vector< std::string > MATCHVEC
Array of strings, sorted/search case insensitive.
SAMPLE_FMT
@ FMT_F16
16 bit floating point
@ FMT_F32
32 bit floating point
@ FMT_F24
24 bit floating point
@ FMT_8
8 bit integer
@ FMT_32
32 bit integer
@ FMT_16
16 bit integer
@ FMT_DONTCARE
Don't care, leave to FFmpegfs to choose.
@ FMT_F64
64 bit floating point
@ FMT_24
24 bit integer
@ FMT_64
64 bit integer
static const AUDIOCODEC_MAP audiocodec_map
List of audio codecs.
Definition ffmpegfs.cc:461
static int get_value(const std::string &arg, int *value)
Get value from command line string. Finds whatever is after the "=" sign.
Definition ffmpegfs.cc:1636
int main(int argc, char *argv[])
Main program entry point.
Definition ffmpegfs.cc:2374
static const VIDEOCODEC_MAP videocodec_map
List of video codecs.
Definition ffmpegfs.cc:478
static int get_size(const std::string &arg, size_t *size)
Read size: .
Definition ffmpegfs.cc:995
std::map< const std::string, HWACCEL, comp > HWACCEL_MAP
Map command line option to HWACCEL struct.
Definition ffmpegfs.cc:450
std::string get_recodesame_text(RECODESAME recode)
Convert RECODESAME enum to human readable text.
Definition ffmpegfs.cc:1313
#define AV_PROFILE_UNKNOWN
Compatibility alias for older FFmpeg versions that only define FF_PROFILE_UNKNOWN.
Definition ffmpegfs.cc:77
std::map< const std::string, const AVCodecID, comp > VIDEOCODEC_MAP
Map command line option to video AVCodecID.
Definition ffmpegfs.cc:455
static HWACCEL_MAP hwaccel_map
Definition ffmpegfs.cc:556
#define FFMPEGFS_OPT(templ, param, value)
Definition ffmpegfs.cc:297
static void ffmpeg_log(void *ptr, int level, const char *fmt, va_list vl)
Custom FFmpeg log function. Used with av_log_set_callback().
Definition ffmpegfs.cc:2183
static const SAMPLE_FMT_MAP sample_fmt_map
Definition ffmpegfs.cc:619
static int get_hwaccel(const std::string &arg, HWACCELAPI *hwaccel_API, AVHWDeviceType *hwaccel_device_type)
Get type of hardware acceleration. To keep it simple, currently all values are accepted.
Definition ffmpegfs.cc:1476
static int get_seek_time_diff(const std::string &arg, int64_t *value)
Get seek time diff. Input value must be in seconds.
Definition ffmpegfs.cc:1448
static int get_audiocodec(const std::string &arg, AVCodecID *audio_codec)
Get the audio codec.
Definition ffmpegfs.cc:1141
FFMPEGFS_PARAMS params
FFmpegfs command line parameters.
Definition ffmpegfs.cc:81
static bool init_logging(const std::string &logfile, const std::string &max_level, bool to_stderr, bool to_syslog)
Inititalise logging facility.
Definition ffmpegfs.cc:2345
std::map< const std::string, const AUTOCOPY, comp > AUTOCOPY_MAP
Map command line option to AUTOCOPY enum.
Definition ffmpegfs.cc:438
std::map< const std::string, const AVCodecID, comp > CODEC_MAP
Map command line option to AVCodecID.
Definition ffmpegfs.cc:451
static int get_bitrate(const std::string &arg, BITRATE *bitrate)
Get formatted bitrate.
Definition ffmpegfs.cc:718
std::map< const std::string, const SAMPLE_FMT, comp > SAMPLE_FMT_MAP
Map command line option to SAMPLE_FMT.
Definition ffmpegfs.cc:452
std::map< const std::string, const AVCodecID, comp > AUDIOCODEC_MAP
Map command line option to audio AVCodecID.
Definition ffmpegfs.cc:454
static void usage()
Print program usage info.
Definition ffmpegfs.cc:666
static const LEVEL_MAP prores_level_map
Definition ffmpegfs.cc:529
static const AUTOCOPY_MAP autocopy_map
Definition ffmpegfs.cc:493
std::map< const std::string, const PRORESLEVEL, comp > LEVEL_MAP
Map command line option to LEVEL enum.
Definition ffmpegfs.cc:440
static int get_videocodec(const std::string &arg, AVCodecID *video_codec)
Get the video codec.
Definition ffmpegfs.cc:1179
static struct fuse_opt ffmpegfs_opts[]
Definition ffmpegfs.cc:307
static const PROFILE_MAP profile_map
Definition ffmpegfs.cc:505
static int get_profile(const std::string &arg, PROFILE *profile)
Get profile option.
Definition ffmpegfs.cc:1329
static int get_desttype(const std::string &arg, FFMPEGFS_FORMAT_ARR &format)
Get destination type.
Definition ffmpegfs.cc:1087
static int get_level(const std::string &arg, PRORESLEVEL *level)
Get ProRes level.
Definition ffmpegfs.cc:1376
std::string get_profile_text(PROFILE profile)
Convert PROFILE enum to human readable text.
Definition ffmpegfs.cc:1359
const char * value_or_none(const char *value)
Return a printable parameter value.
Definition ffmpegfs.cc:2063
static int get_hwaccel_dec_blocked(const std::string &arg, HWACCEL_BLOCKED_MAP **hwaccel_dec_blocked)
Get list of codecs and optional profiles blocked for hardware accelerated decoding.
Definition ffmpegfs.cc:1545
static void print_params()
Print currently selected parameters.
Definition ffmpegfs.cc:2071
static const CODEC_MAP hwaccel_codec_map
Definition ffmpegfs.cc:603
std::string get_level_text(PRORESLEVEL level)
Convert PRORESLEVEL enum to human readable text.
Definition ffmpegfs.cc:1407
std::string get_sampleformat_text(SAMPLE_FMT sample_fmt)
Convert SAMPLE_FMT enum to human readable text.
Definition ffmpegfs.cc:872
static int get_sampleformat(const std::string &arg, SAMPLE_FMT *sample_fmt)
Get sample format.
Definition ffmpegfs.cc:838
static int ffmpegfs_opt_proc(__attribute__((unused)) void *data, const char *arg, int key, struct fuse_args *outargs)
FUSE option parsing function.
Definition ffmpegfs.cc:1768
static int get_segment_duration(const std::string &arg, int64_t *value)
Get HLS segment duration. Input value must be in seconds.
Definition ffmpegfs.cc:1423
static void build_device_type_list()
Build list of available device types. Builds a list of device types supported by the current FFmpeg l...
Definition ffmpegfs.cc:2039
static int get_time(const std::string &arg, time_t *time)
Get formatted time,.
Definition ffmpegfs.cc:896
std::string get_video_codec_text(AVCodecID video_codec)
Convert AVCodecID enum for video codec to human readable text.
Definition ffmpegfs.cc:1257
std::map< const std::string, const PROFILE, comp > PROFILE_MAP
Map command line option to PROFILE enum.
Definition ffmpegfs.cc:439
static int get_recodesame(const std::string &arg, RECODESAME *recode)
Get recode option.
Definition ffmpegfs.cc:1283
static void list_options(const char *info, const T &map)
Iterate through all elements in map print all keys.
Definition ffmpegfs.cc:683
static const RECODESAME_MAP recode_map
Definition ffmpegfs.cc:541
FFMPEGFS_FORMAT_ARR ffmpeg_format
Two FFmpegfs_Format infos, 0: video file, 1: audio file.
Definition ffmpegfs.cc:80
std::map< const std::string, const RECODESAME, comp > RECODESAME_MAP
Map command line option to RECODESAME enum.
Definition ffmpegfs.cc:441
static int get_samplerate(const std::string &arg, int *samplerate)
Get formatted sample rate.
Definition ffmpegfs.cc:786
std::string get_autocopy_text(AUTOCOPY autocopy)
Convert AUTOCOPY enum to human readable text.
Definition ffmpegfs.cc:1267
std::string get_audio_codec_text(AVCodecID audio_codec)
Convert AVCodecID enum for audio codec to human readable text.
Definition ffmpegfs.cc:1247
static int get_codec(const std::string &codec, AVCodecID *codec_id)
Get AVCodecID for codec string.
Definition ffmpegfs.cc:1520
bool check_hwaccel_dec_blocked(AVCodecID codec_id, int profile)
Check if codec_id and the optional profile are in the block list.
Definition ffmpegfs.cc:1596
std::string get_hwaccel_API_text(HWACCELAPI hwaccel_API)
Get the selected hardware acceleration as text.
Definition ffmpegfs.cc:1614
static int get_autocopy(const std::string &arg, AUTOCOPY *autocopy)
Get autocopy option.
Definition ffmpegfs.cc:1217
static bool set_defaults()
Set default values.
Definition ffmpegfs.cc:2021
Main include for FFmpegfs project.
fuse_operations ffmpegfs_ops
Fuse operations struct.
Definition fuseops.cc:100
void transcoder_cache_path(std::string *path)
Get transcoder cache path.
Definition transcode.cc:336
bool docker_client
True if running inside a Docker container.
Definition fuseops.cc:98
HWACCELAPI
Hardware acceleration types.
Definition ffmpegfs.h:120
bool transcoder_init()
Initialise transcoder, create cache.
Definition transcode.cc:370
std::multimap< AVCodecID, int > HWACCEL_BLOCKED_MAP
Map command line option to AVCodecID.
Definition ffmpegfs.h:154
FFMPEGFS_FORMAT_ARR ffmpeg_format
Two FFmpegfs_Format infos, 0: video file, 1: audio file.
Definition ffmpegfs.cc:80
bool transcoder_cache_clear()
Clear transcoder cache.
bool transcoder_cache_maintenance()
Run cache maintenance.
void init_fuse_ops()
Initialise FUSE operation structure.
Definition fuseops.cc:247
VIRTUALFILE const * LPCVIRTUALFILE
Pointer to const version of VIRTUALFILE.
Definition fileio.h:254
Provide various log facilities to stderr, disk or syslog.
constexpr Logging::LOGLEVEL LOGDEBUG
Shorthand for log level DEBUG.
Definition logging.h:459
constexpr Logging::LOGLEVEL LOGTRACE
Shorthand for log level TRACE.
Definition logging.h:460
constexpr Logging::LOGLEVEL LOGWARN
Shorthand for log level WARNING.
Definition logging.h:457
constexpr Logging::LOGLEVEL LOGERROR
Shorthand for log level ERROR.
Definition logging.h:456
constexpr Logging::LOGLEVEL LOGINFO
Shorthand for log level INFO.
Definition logging.h:458
Global program parameters.
Definition ffmpegfs.h:162
std::string m_scriptsource
Source script.
Definition ffmpegfs.h:230
std::string m_hwaccel_enc_device
Encoder device. May be AUTO to auto detect or empty.
Definition ffmpegfs.h:218
int m_log_stderr
Log output to standard error.
Definition ffmpegfs.h:234
time_t m_cache_maintenance
Prune timer interval.
Definition ffmpegfs.h:247
bool smart_transcode() const
Check for smart transcode mode.
Definition ffmpegfs.cc:237
AVHWDeviceType m_hwaccel_dec_device_type
Enable hardware acceleration buffering for decoder.
Definition ffmpegfs.h:220
time_t m_max_inactive_suspend
Time (seconds) that must elapse without access until transcoding is suspended.
Definition ffmpegfs.h:239
int m_deinterlace
1: deinterlace video, 0: no deinterlace
Definition ffmpegfs.h:211
int m_decoding_errors
Break transcoding on decoding error.
Definition ffmpegfs.h:252
int m_oldnamescheme
Use old output name scheme, can create duplicate filenames.
Definition ffmpegfs.h:254
AVHWDeviceType m_hwaccel_enc_device_type
Enable hardware acceleration buffering for encoder.
Definition ffmpegfs.h:217
time_t m_expiry_time
Time (seconds) after which an cache entry is deleted.
Definition ffmpegfs.h:238
int m_no_subtitles
0: allow subtitles, 1: do no transcode subtitles
Definition ffmpegfs.h:224
FFMPEGFS_PARAMS & operator=(const FFMPEGFS_PARAMS &other) noexcept
Make copy from other FFMPEGFS_PARAMS object.
Definition ffmpegfs.cc:164
int m_clear_cache
Clear cache on start up.
Definition ffmpegfs.h:249
std::string m_hwaccel_dec_device
Decoder device. May be AUTO to auto detect or empty.
Definition ffmpegfs.h:221
const FFmpegfs_Format * current_format(LPCVIRTUALFILE virtualfile) const
Get FFmpegfs_Format for a virtual file.
Definition ffmpegfs.cc:242
int m_audiochannels
Max. number of audio channels.
Definition ffmpegfs.h:205
int64_t m_min_seek_time_diff
Minimum time diff from current to next requested segment to perform a seek, in AV_TIME_BASE fractiona...
Definition ffmpegfs.h:214
int m_videowidth
Output video width.
Definition ffmpegfs.h:209
BITRATE m_videobitrate
Output video bit rate (bits per second)
Definition ffmpegfs.h:208
HWACCELAPI m_hwaccel_dec_API
Decoder API.
Definition ffmpegfs.h:219
size_t m_prebuffer_size
Number of bytes that will be decoded before the output can be accessed.
Definition ffmpegfs.h:242
int m_videoheight
Output video height.
Definition ffmpegfs.h:210
time_t m_prebuffer_time
Playing time that will be decoded before the output can be accessed.
Definition ffmpegfs.h:241
int64_t m_segment_duration
Duration of one HLS segment file, in AV_TIME_BASE fractional seconds.
Definition ffmpegfs.h:213
BITRATE m_audiobitrate
Output audio bit rate (bits per second)
Definition ffmpegfs.h:203
std::string m_cachepath
Disk cache path, defaults to $XDG_CACHE_HOME.
Definition ffmpegfs.h:245
int m_prune_cache
Prune cache immediately.
Definition ffmpegfs.h:248
RECODESAME m_recodesame
Recode to same format options.
Definition ffmpegfs.h:199
SAMPLE_FMT m_sample_fmt
Sample format.
Definition ffmpegfs.h:206
PROFILE m_profile
Target profile: Firefox, MS Edge/IE or other.
Definition ffmpegfs.h:200
int m_audiosamplerate
Output audio sample rate (in Hz)
Definition ffmpegfs.h:204
size_t m_max_cache_size
Max. cache size in MB. When exceeded, oldest entries will be pruned.
Definition ffmpegfs.h:243
AVCodecID m_video_codec
Either AV_CODEC_ID_NONE for default, or a user selected codec.
Definition ffmpegfs.h:197
unsigned int m_max_threads
Max. number of recoder threads.
Definition ffmpegfs.h:250
int m_disable_cache
Disable cache.
Definition ffmpegfs.h:246
std::unique_ptr< MATCHVEC > m_hide_extensions
Set of extensions to block/hide. Must be a pointer as the fuse API cannot handle advanced c++ objects...
Definition ffmpegfs.h:256
time_t m_max_inactive_abort
Time (seconds) that must elapse without access until transcoding is aborted.
Definition ffmpegfs.h:240
int m_min_dvd_chapter_duration
Min. DVD chapter duration. Shorter chapters will be ignored.
Definition ffmpegfs.h:253
std::string m_logfile
Output filename if logging to file.
Definition ffmpegfs.h:236
std::string m_log_maxlevel
Max. log level.
Definition ffmpegfs.h:233
std::string m_mountpath
Mount path: Files from m_mountpath will be mapped to this directory.
Definition ffmpegfs.h:193
AVCodecID m_audio_codec
Either AV_CODEC_ID_NONE for default, or a user selected codec.
Definition ffmpegfs.h:196
PRORESLEVEL m_level
Level, currently proxy/hq/lt/HQ (ProRes only)
Definition ffmpegfs.h:201
size_t m_min_diskspace
Min. diskspace required for cache.
Definition ffmpegfs.h:244
int m_noalbumarts
Skip album arts.
Definition ffmpegfs.h:226
int m_enablescript
Enable virtual script.
Definition ffmpegfs.h:228
std::unique_ptr< MATCHVEC > m_include_extensions
Set of extensions to include. If empty, include all. Must be a pointer as the fuse API cannot handle ...
Definition ffmpegfs.h:255
HWACCEL_BLOCKED_MAP * m_hwaccel_dec_blocked
List of blocked decoders and optional profiles.
Definition ffmpegfs.h:222
int m_debug
Debug mode (stay in foreground.
Definition ffmpegfs.h:232
std::string m_scriptfile
Script name.
Definition ffmpegfs.h:229
int m_win_smb_fix
Experimental Windows fix for access to EOF at file open.
Definition ffmpegfs.h:258
int m_log_syslog
Log output to system log.
Definition ffmpegfs.h:235
std::string m_basepath
Base path: Files from this directory (including all sub directories) will be mapped to m_mountpath.
Definition ffmpegfs.h:192
HWACCELAPI m_hwaccel_enc_API
Encoder API.
Definition ffmpegfs.h:216
AUTOCOPY m_autocopy
Copy streams if codec matches.
Definition ffmpegfs.h:198
Hardware acceleration device and type.
Definition ffmpegfs.cc:444
HWACCELAPI m_hwaccel_API
Acceleration API, e.g VAAPI, MMAL or OMX.
Definition ffmpegfs.cc:446
AVHWDeviceType m_hwaccel_device_type
Hardware buffering type, NONE if not used.
Definition ffmpegfs.cc:447
bool m_supported
true if API supported, false if not
Definition ffmpegfs.cc:445