36#pragma GCC diagnostic push
37#pragma GCC diagnostic ignored "-Wconversion"
38#pragma GCC diagnostic ignored "-Wsign-conversion"
39#include <libswscale/swscale.h>
40#include "libavutil/ffversion.h"
41#include <libavcodec/avcodec.h>
42#pragma GCC diagnostic pop
71#pragma GCC diagnostic push
72#pragma GCC diagnostic ignored "-Wpedantic"
74#pragma GCC diagnostic pop
82#pragma GCC diagnostic push
83#pragma GCC diagnostic ignored "-Wconversion"
84#pragma GCC diagnostic ignored "-Wsign-conversion"
85#include <libswresample/swresample.h>
86#pragma GCC diagnostic pop
91static int is_device(__attribute__((unused))
const AVClass *avclass);
92static std::string
ffmpeg_libinfo(
bool lib_exists, __attribute__((unused))
unsigned int version, __attribute__((unused))
const char *cfg,
int version_minor,
int version_major,
int version_micro,
const char * libname);
94#ifndef AV_ERROR_MAX_STRING_SIZE
95#define AV_ERROR_MAX_STRING_SIZE 128
98typedef std::map<const std::string, const FILETYPE, comp>
FILETYPE_MAP;
105 {
"mp3", FILETYPE::MP3 },
106 {
"mp4", FILETYPE::MP4 },
107 {
"wav", FILETYPE::WAV },
108 {
"ogg", FILETYPE::OGG },
109 {
"webm", FILETYPE::WEBM },
110 {
"mov", FILETYPE::MOV },
111 {
"aiff", FILETYPE::AIFF },
112 {
"opus", FILETYPE::OPUS },
113 {
"prores", FILETYPE::PRORES },
114 {
"alac", FILETYPE::ALAC },
115 {
"png", FILETYPE::PNG },
116 {
"jpg", FILETYPE::JPG },
117 {
"bmp", FILETYPE::BMP },
118 {
"ts", FILETYPE::TS },
119 {
"hls", FILETYPE::HLS },
120 {
"flac", FILETYPE::FLAC },
121 {
"mkv", FILETYPE::MKV },
125 : m_format_map{ {
SAMPLE_FMT::FMT_DONTCARE, { { AV_CODEC_ID_NONE }, { AV_CODEC_ID_NONE }, { AV_CODEC_ID_NONE }, AV_SAMPLE_FMT_NONE }}}
126 , m_albumart_supported(
false)
131 std::string format_name,
134 bool albumart_supported
136 : m_format_name(std::move(format_name))
137 , m_fileext(std::move(fileext))
138 , m_format_map(std::move(format))
139 , m_albumart_supported(albumart_supported)
150 return AV_CODEC_ID_NONE;
155 return (it->second.m_video_codec[0]);
166 for (
const AVCodecID & video_codec_id : it->second.m_video_codec)
168 if (video_codec_id == codec_id)
183 for (
const AVCodecID & video_codec_id : it->second.m_video_codec)
203 return AV_CODEC_ID_NONE;
208 return (it->second.m_audio_codec[0]);
219 for (
const AVCodecID & audio_codec_id : it->second.m_audio_codec)
221 if (audio_codec_id == codec_id)
236 for (
const AVCodecID & audio_codec_id : it->second.m_audio_codec)
255 return AV_SAMPLE_FMT_NONE;
258 return (it->second.m_sample_format);
289 return AV_CODEC_ID_NONE;
293 for (
const AVCodecID & subtitle_codec_id : it->second.m_subtitle_codec)
296 if (subtitle_codec_id == codec_id || (codec_id == AV_CODEC_ID_DVD_SUBTITLE && subtitle_codec_id == AV_CODEC_ID_DVB_SUBTITLE))
298 return subtitle_codec_id;
306 for (
const AVCodecID & subtitle_codec_id : it->second.m_subtitle_codec)
310 return subtitle_codec_id;
317 for (
const AVCodecID & subtitle_codec_id : it->second.m_subtitle_codec)
321 return subtitle_codec_id;
327 return AV_CODEC_ID_NONE;
360 { AV_CODEC_ID_NONE },
362 { AV_CODEC_ID_NONE },
382 { AV_CODEC_ID_H264, AV_CODEC_ID_H265, AV_CODEC_ID_MPEG1VIDEO, AV_CODEC_ID_MPEG2VIDEO },
383 { AV_CODEC_ID_AAC, AV_CODEC_ID_MP3 },
384 { AV_CODEC_ID_MOV_TEXT },
404 { AV_CODEC_ID_NONE },
405 { AV_CODEC_ID_PCM_S16LE },
406 { AV_CODEC_ID_NONE },
413 { AV_CODEC_ID_NONE },
414 { AV_CODEC_ID_PCM_U8 },
415 { AV_CODEC_ID_NONE },
422 { AV_CODEC_ID_NONE },
423 { AV_CODEC_ID_PCM_S16LE },
424 { AV_CODEC_ID_NONE },
431 { AV_CODEC_ID_NONE },
432 { AV_CODEC_ID_PCM_S24LE },
433 { AV_CODEC_ID_NONE },
441 { AV_CODEC_ID_NONE },
442 { AV_CODEC_ID_PCM_S32LE },
443 { AV_CODEC_ID_NONE },
451 { AV_CODEC_ID_NONE },
452 { AV_CODEC_ID_PCM_S64LE },
453 { AV_CODEC_ID_NONE },
460 { AV_CODEC_ID_NONE },
461 { AV_CODEC_ID_PCM_F16LE },
462 { AV_CODEC_ID_NONE },
469 { AV_CODEC_ID_NONE },
470 { AV_CODEC_ID_PCM_F24LE },
471 { AV_CODEC_ID_NONE },
478 { AV_CODEC_ID_NONE },
479 { AV_CODEC_ID_PCM_F32LE },
480 { AV_CODEC_ID_NONE },
487 { AV_CODEC_ID_NONE },
488 { AV_CODEC_ID_PCM_F64LE },
489 { AV_CODEC_ID_NONE },
509 { AV_CODEC_ID_THEORA },
510 { AV_CODEC_ID_VORBIS },
511 { AV_CODEC_ID_NONE },
531 { AV_CODEC_ID_VP9, AV_CODEC_ID_VP8, AV_CODEC_ID_AV1 },
532 { AV_CODEC_ID_OPUS, AV_CODEC_ID_VORBIS },
533 { AV_CODEC_ID_WEBVTT },
553 { AV_CODEC_ID_H264, AV_CODEC_ID_H265, AV_CODEC_ID_MPEG1VIDEO, AV_CODEC_ID_MPEG2VIDEO },
554 { AV_CODEC_ID_AAC, AV_CODEC_ID_AC3, AV_CODEC_ID_MP3 },
555 { AV_CODEC_ID_MOV_TEXT },
575 { AV_CODEC_ID_NONE },
576 { AV_CODEC_ID_PCM_S16BE },
577 { AV_CODEC_ID_NONE },
584 { AV_CODEC_ID_NONE },
585 { AV_CODEC_ID_PCM_S16BE },
586 { AV_CODEC_ID_NONE },
593 { AV_CODEC_ID_NONE },
594 { AV_CODEC_ID_PCM_S32BE },
595 { AV_CODEC_ID_NONE },
615 { AV_CODEC_ID_NONE },
616 { AV_CODEC_ID_OPUS },
617 { AV_CODEC_ID_NONE },
637 { AV_CODEC_ID_PRORES },
638 { AV_CODEC_ID_PCM_S16LE },
639 { AV_CODEC_ID_MOV_TEXT },
659 { AV_CODEC_ID_NONE },
660 { AV_CODEC_ID_ALAC },
661 { AV_CODEC_ID_NONE },
668 { AV_CODEC_ID_NONE },
669 { AV_CODEC_ID_ALAC },
670 { AV_CODEC_ID_NONE },
677 { AV_CODEC_ID_NONE },
678 { AV_CODEC_ID_ALAC },
679 { AV_CODEC_ID_NONE },
700 { AV_CODEC_ID_NONE },
701 { AV_CODEC_ID_NONE },
721 { AV_CODEC_ID_MJPEG },
722 { AV_CODEC_ID_NONE },
723 { AV_CODEC_ID_NONE },
744 { AV_CODEC_ID_NONE },
745 { AV_CODEC_ID_NONE },
765 { AV_CODEC_ID_H264, AV_CODEC_ID_H265, AV_CODEC_ID_MPEG1VIDEO, AV_CODEC_ID_MPEG2VIDEO },
766 { AV_CODEC_ID_AAC, AV_CODEC_ID_AC3, AV_CODEC_ID_MP3 },
767 { AV_CODEC_ID_DVB_SUBTITLE },
788 { AV_CODEC_ID_H264, AV_CODEC_ID_H265, AV_CODEC_ID_MPEG1VIDEO, AV_CODEC_ID_MPEG2VIDEO },
789 { AV_CODEC_ID_AAC, AV_CODEC_ID_AC3, AV_CODEC_ID_MP3 },
790 { AV_CODEC_ID_DVB_SUBTITLE },
810 { AV_CODEC_ID_NONE },
811 { AV_CODEC_ID_FLAC },
812 { AV_CODEC_ID_NONE },
819 { AV_CODEC_ID_NONE },
820 { AV_CODEC_ID_FLAC },
821 { AV_CODEC_ID_NONE },
828 { AV_CODEC_ID_NONE },
829 { AV_CODEC_ID_FLAC },
830 { AV_CODEC_ID_NONE },
850 { AV_CODEC_ID_H264, AV_CODEC_ID_H265, AV_CODEC_ID_MPEG1VIDEO, AV_CODEC_ID_MPEG2VIDEO },
851 { AV_CODEC_ID_AAC, AV_CODEC_ID_AC3, AV_CODEC_ID_MP3 },
852 { AV_CODEC_ID_ASS, AV_CODEC_ID_SUBRIP, AV_CODEC_ID_WEBVTT, AV_CODEC_ID_DVB_SUBTITLE },
863 m_cur_opts(&m_empty_options),
985 if (path->back() !=
'/')
1004 if (path->back() ==
'/')
1014 std::shared_ptr<char[]> p =
new_strdup(*filepath);
1022 *filepath = dirname(p.get());
1030 std::shared_ptr<char[]> p =
new_strdup(*filepath);
1038 *filepath = basename(p.get());
1047 found = filepath->rfind(
'.');
1049 if (found != std::string::npos)
1052 filepath->resize(found);
1058bool find_ext(std::string * ext,
const std::string & filename)
1062 found = filename.rfind(
'.');
1064 if (found == std::string::npos)
1073 *ext = filename.substr(found + 1);
1078bool check_ext(
const std::string & ext,
const std::string & filename)
1081 return (
find_ext(&ext1, filename) && ext1 == ext);
1084const std::string &
replace_ext(std::string * filepath,
const std::string & ext)
1088 found = filepath->rfind(
'.');
1090 if (found == std::string::npos)
1098 filepath->resize(found + 1);
1106const std::string &
append_ext(std::string * filepath,
const std::string & ext)
1110 found = filepath->rfind(
'.');
1112 if (found == std::string::npos ||
strcasecmp(filepath->substr(found + 1), ext) != 0)
1115 *filepath +=
'.' + ext;
1123 size_t n = str.size() + 1;
1124 std::shared_ptr<char[]> p(
new (std::nothrow)
char[n]);
1132 strncpy(p.get(), str.c_str(), n);
1141 std::array<char, AV_ERROR_MAX_STRING_SIZE + 1> error;
1142 av_strerror(errnum, error.data(), error.size() - 1);
1143 return error.data();
1147 return strerror(errnum);
1151int64_t
ffmpeg_rescale_q(int64_t ts,
const AVRational & timebase_in,
const AVRational &timebase_out)
1153 if (ts == AV_NOPTS_VALUE)
1155 return AV_NOPTS_VALUE;
1163 return av_rescale_q(ts, timebase_in, timebase_out);
1168 if (ts == AV_NOPTS_VALUE)
1170 return AV_NOPTS_VALUE;
1178 return av_rescale_q_rnd(ts, timebase_in, timebase_out,
static_cast<AVRounding
>(AV_ROUND_UP |
AV_ROUND_PASS_MINMAX));
1181#if !HAVE_MEDIA_TYPE_STRING
1186 case AVMEDIA_TYPE_VIDEO:
1188 case AVMEDIA_TYPE_AUDIO:
1190 case AVMEDIA_TYPE_DATA:
1192 case AVMEDIA_TYPE_SUBTITLE:
1194 case AVMEDIA_TYPE_ATTACHMENT:
1195 return "attachment";
1213static std::string
ffmpeg_libinfo(
bool lib_exists, __attribute__((unused))
unsigned int version, __attribute__((unused))
const char *cfg,
int version_minor,
int version_major,
int version_micro,
const char * libname)
1229#define PRINT_LIB_INFO(libname, LIBNAME) \
1230 ffmpeg_libinfo(true, libname##_version(), libname##_configuration(), \
1231 LIB##LIBNAME##_VERSION_MAJOR, LIB##LIBNAME##_VERSION_MINOR, LIB##LIBNAME##_VERSION_MICRO, #libname)
1237 info =
"FFmpeg Version : " FFMPEG_VERSION
"\n";
1258static int is_device(__attribute__((unused))
const AVClass *avclass)
1269 const AVInputFormat *ifmt =
nullptr;
1270 const AVOutputFormat *ofmt =
nullptr;
1271 const char *last_name;
1275 " D. = Demuxing supported\n"
1276 " .E = Muxing supported\n"
1277 " --\n", device_only ?
"Devices:" :
"File formats:");
1283 const char *name =
nullptr;
1284 const char *long_name =
nullptr;
1285 const char *extensions =
nullptr;
1287 void *ofmt_opaque =
nullptr;
1288 ofmt_opaque =
nullptr;
1289 while ((ofmt = av_muxer_iterate(&ofmt_opaque)))
1292 if (!is_dev && device_only)
1297 if ((!name || strcmp(ofmt->name, name) < 0) &&
1298 strcmp(ofmt->name, last_name) > 0)
1301 long_name = ofmt->long_name;
1306 void *ifmt_opaque =
nullptr;
1307 ifmt_opaque =
nullptr;
1308 while ((ifmt = av_demuxer_iterate(&ifmt_opaque)) !=
nullptr)
1311 if (!is_dev && device_only)
1316 if ((!name || strcmp(ifmt->name, name) < 0) &&
1317 strcmp(ifmt->name, last_name) > 0)
1320 long_name = ifmt->long_name;
1321 extensions = ifmt->extensions;
1324 if (name && strcmp(ifmt->name, name) == 0)
1330 if (name ==
nullptr)
1336 if (extensions ==
nullptr)
1341 std::printf(
" %s%s %-15s %-15s %s\n",
1346 (long_name !=
nullptr) ? long_name :
" ");
1353 const AVCodecDescriptor * pCodecDescriptor;
1354 const char * psz =
"unknown";
1356 pCodecDescriptor = avcodec_descriptor_get(codec_id);
1358 if (pCodecDescriptor !=
nullptr)
1360 if (pCodecDescriptor->long_name !=
nullptr && long_name)
1362 psz = pCodecDescriptor->long_name;
1367 psz = pCodecDescriptor->name;
1374int mktree(
const std::string & path, mode_t mode)
1378 if (buffer ==
nullptr)
1385 char *p = strtok_r(buffer.get(),
"/", &saveptr);
1388 while (p !=
nullptr)
1397 newstat = mkdir(dir.c_str(), mode);
1399 if (!status && newstat && errno != EEXIST)
1407 p = strtok_r(
nullptr,
"/", &saveptr);
1413void tempdir(std::string & path)
1415 const char *temp = getenv(
"TMPDIR");
1417 if (temp !=
nullptr)
1436 return (filetype == FILETYPE::MP3 || filetype == FILETYPE::MP4);
1445 catch (
const std::out_of_range& )
1448 return FILETYPE::UNKNOWN;
1465 std::vector<std::string> desttype =
split(desttypelist,
",");
1466 FILETYPE filetype = FILETYPE::UNKNOWN;
1469 for (
size_t n = 0; n < desttype.size() && filetype != FILETYPE::UNKNOWN; n++)
1479 std::memset(id3v1,
' ',
sizeof(
ID3v1));
1480 std::memcpy(&id3v1->
m_tag,
"TAG", 3);
1493 if (value == AV_NOPTS_VALUE)
1499 return strsprintf(&buffer,
"%" PRId64, value);
1504 if (value ==
static_cast<BITRATE>(AV_NOPTS_VALUE))
1509 if (value > 1000000)
1512 return strsprintf(&buffer,
"%.2f Mbps",
static_cast<double>(value) / 1000000);
1514 else if (value > 1000)
1517 return strsprintf(&buffer,
"%.1f kbps",
static_cast<double>(value) / 1000);
1522 return strsprintf(&buffer,
"%" PRId64
" bps", value);
1528 if (value ==
static_cast<int>(AV_NOPTS_VALUE))
1541 return strsprintf(&buffer,
"%.3f kHz",
static_cast<double>(value) / 1000);
1545#define STR_VALUE(arg) #arg
1546#define X(name) STR_VALUE(name)
1550 if (value == AV_NOPTS_VALUE)
1556 std::string duration;
1557 unsigned hours =
static_cast<unsigned>((value / AV_TIME_BASE) / (3600));
1558 unsigned mins =
static_cast<unsigned>(((value / AV_TIME_BASE) % 3600) / 60);
1559 unsigned secs =
static_cast<unsigned>((value / AV_TIME_BASE) % 60);
1563 duration =
strsprintf(&buffer,
"%02u:", hours);
1566 duration +=
strsprintf(&buffer,
"%02u:%02u", mins, secs);
1569 unsigned decimals =
static_cast<unsigned>(value % AV_TIME_BASE);
1570 duration +=
strsprintf(&buffer,
".%0*u",
sizeof(
X(AV_TIME_BASE)) - 2, decimals).substr(0, fracs + 1);
1582 if (value ==
static_cast<time_t
>(AV_NOPTS_VALUE))
1595 weeks =
static_cast<int>(value / (60*60*24*7));
1596 value -= weeks * (60*60*24*7);
1597 days =
static_cast<int>(value / (60*60*24));
1598 value -= days * (60*60*24);
1599 hours =
static_cast<int>(value / (60*60));
1600 value -= hours * (60*60);
1601 mins =
static_cast<int>(value / (60));
1602 value -= mins * (60);
1603 secs =
static_cast<int>(value);
1635 if (value ==
static_cast<uint64_t
>(AV_NOPTS_VALUE))
1640 if (value > 1024*1024*1024*1024LL)
1643 return strsprintf(&buffer,
"%.3f TB",
static_cast<double>(value) / (1024*1024*1024*1024LL));
1645 else if (value > 1024*1024*1024)
1648 return strsprintf(&buffer,
"%.2f GB",
static_cast<double>(value) / (1024*1024*1024));
1650 else if (value > 1024*1024)
1653 return strsprintf(&buffer,
"%.1f MB",
static_cast<double>(value) / (1024*1024));
1655 else if (value > 1024)
1658 return strsprintf(&buffer,
"%.1f KB",
static_cast<double>(value) / (1024));
1663 return strsprintf(&buffer,
"%" PRIu64
" bytes", value);
1675 if (size_resulting >= size_predicted)
1677 size_t value = size_resulting - size_predicted;
1682 size_t value = size_predicted - size_resulting;
1689 if (size_resulting >= size_predicted)
1692 size_t value = size_resulting - size_predicted;
1698 size_t value = size_predicted - size_resulting;
1708static void print_fps(
double d,
const char *postfix)
1710 long v = lrint(d * 100);
1713 std::printf(
"%1.4f %s\n", d, postfix);
1717 std::printf(
"%3.2f %s\n", d, postfix);
1719 else if (v % (100 * 1000))
1721 std::printf(
"%1.0f %s\n", d, postfix);
1725 std::printf(
"%1.0fk %s\n", d / 1000, postfix);
1733 AVCodecContext *avctx = avcodec_alloc_context3(
nullptr);
1734 if (avctx ==
nullptr)
1736 return AVERROR(ENOMEM);
1739 ret = avcodec_parameters_to_context(avctx, stream->codecpar);
1742 avcodec_free_context(&avctx);
1753 int fps = stream->avg_frame_rate.den && stream->avg_frame_rate.num;
1754 int tbr = stream->r_frame_rate.den && stream->r_frame_rate.num;
1755 int tbn = stream->time_base.den && stream->time_base.num;
1756 int tbc = avctx->time_base.den && avctx->time_base.num;
1759 print_fps(av_q2d(stream->avg_frame_rate),
"avg fps");
1761 print_fps(av_q2d(stream->r_frame_rate),
"Real base framerate (tbr)");
1763 print_fps(1 / av_q2d(stream->time_base),
"stream timebase (tbn)");
1765 print_fps(1 / av_q2d(avctx->time_base),
"codec timebase (tbc)");
1767 avcodec_free_context(&avctx);
1774 std::string fourcc2str(AV_FOURCC_MAX_STRING_SIZE,
'\0');
1775 av_fourcc_make_string(&fourcc2str[0], fourcc);
1776 fourcc2str.resize(std::strlen(fourcc2str.c_str()));
1781void exepath(std::string * path)
1783 std::array<char, PATH_MAX + 1> result;
1784 ssize_t count = readlink(
"/proc/self/exe", result.data(), result.size() - 1);
1787 *path = dirname(result.data());
1796std::string &
ltrim(std::string &s)
1798 s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not_fn(std::function<
int(
int)>(isspace))));
1802std::string &
rtrim(std::string &s)
1804 s.erase(std::find_if(s.rbegin(), s.rend(), std::not_fn(std::function<
int(
int)>(isspace))).base(), s.end());
1808std::string &
trim(std::string &s)
1813std::string
replace_all(std::string str,
const std::string& from,
const std::string& to)
1818std::string
replace_all(std::string *str,
const std::string& from,
const std::string& to)
1820 size_t start_pos = 0;
1821 while ((start_pos = str->find(from, start_pos)) != std::string::npos)
1823 str->replace(start_pos, from.length(), to);
1824 start_pos += to.length();
1829bool replace_start(std::string *str,
const std::string& from,
const std::string& to)
1831#if __cplusplus >= 202002L
1833 if (str->starts_with(from) == 0)
1835 if (str->find(from, 0) == 0)
1838 str->replace(0, from.length(), to);
1845int strcasecmp(
const std::string & s1,
const std::string & s2)
1850int reg_compare(
const std::string & value,
const std::string & pattern, std::regex::flag_type flag)
1856 std::regex rgx(pattern, flag);
1858 reti = (std::regex_search(value, rgx) ==
true) ? 0 : 1;
1860 catch(
const std::regex_error& e)
1862 std::cerr <<
"regex_error caught: " << e.what() << std::endl;
1863 if(e.code() == std::regex_constants::error_brack)
1864 std::cerr <<
"The code was error_brack" << std::endl;
1872const std::string &
expand_path(std::string *tgt,
const std::string & src)
1874 wordexp_t exp_result;
1875 if (!wordexp(
replace_all(src,
" ",
"\\ ").c_str(), &exp_result, 0))
1877 *tgt = exp_result.we_wordv[0];
1878 wordfree(&exp_result);
1888int is_mount(
const std::string & path)
1894 std::shared_ptr<char[]> orig_name;
1895 struct stat file_stat;
1896 struct stat parent_stat;
1897 char * parent_name =
nullptr;
1901 if (orig_name ==
nullptr)
1903 std::fprintf(stderr,
"is_mount(): Out of memory\n");
1909 parent_name = dirname(orig_name.get());
1912 if (-1 == stat(path.c_str(), &file_stat))
1914 std::fprintf(stderr,
"is_mount(): (%i) %s\n", errno, strerror(errno));
1920 if (!(file_stat.st_mode & S_IFDIR))
1922 std::fprintf(stderr,
"is_mount(): %s is not a directory.\n", path.c_str());
1927 if (-1 == stat(parent_name, &parent_stat))
1929 std::fprintf(stderr,
"is_mount(): (%i) %s\n", errno, strerror(errno));
1943 if (file_stat.st_dev != parent_stat.st_dev || file_stat.st_ino == parent_stat.st_ino)
1962std::vector<std::string>
split(
const std::string& input,
const std::string & regex)
1965 std::regex re(regex);
1966 std::sregex_token_iterator first{input.cbegin(), input.cend(), re, -1},
1968 return {first, last};
1973 std::array<char, PATH_MAX + 1> resolved_name;
1975 if (realpath(filepath->c_str(), resolved_name.data()) !=
nullptr)
1977 *filepath = resolved_name.data();
1983 std::string _filepath(*filepath);
1990 std::string buffer(filepath);
2006bool is_album_art(AVCodecID codec_id,
const AVRational * frame_rate)
2008 if (codec_id == AV_CODEC_ID_PNG || codec_id == AV_CODEC_ID_BMP)
2014 if (codec_id != AV_CODEC_ID_MJPEG)
2020 if (frame_rate !=
nullptr && frame_rate->den)
2022 double dbFrameRate =
static_cast<double>(frame_rate->num) / frame_rate->den;
2025 if (dbFrameRate < 300)
2035int nocasecompare(
const std::string & lhs,
const std::string &rhs)
2044 if (statvfs(path.c_str(), &buf))
2049 return static_cast<size_t>(buf.f_bfree * buf.f_bsize);
2054 std::array<size_t, 3> blocksize_arr = { 0x2000, 0x8000, 0x10000 };
2055 bool ignore =
false;
2057 for (
const size_t & blocksize: blocksize_arr)
2062 match = !(offset % blocksize);
2068 rest = size % offset;
2069 ignore = match && (rest < blocksize);
2080std::string
make_filename(uint32_t file_no,
const std::string & fileext)
2083 return strsprintf(&buffer,
"%06u.%s", file_no, fileext.c_str());
2088 return (access(filename.c_str(), F_OK) != -1);
2093 std::for_each(std::begin(*input), std::end(*input), [](
char& c) {
2094 c =
static_cast<char>(std::toupper(
static_cast<unsigned char>(c)));
2100 std::for_each(std::begin(*input), std::end(*input), [](
char& c) {
2101 c =
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
2107 const char *type_name = av_hwdevice_get_type_name(dev_type);
2108 return (type_name !=
nullptr ? type_name :
"unknown");
2111int to_utf8(std::string & text,
const std::string & encoding)
2113 iconv_t conv = iconv_open(
"UTF-8", encoding.c_str());
2114 if (conv == (iconv_t) -1)
2120 std::vector<char> src;
2121 std::vector<char> dst;
2122 size_t srclen = text.size();
2123 size_t dstlen = 2 * srclen;
2125 src.reserve(srclen + 1);
2126 dst.reserve(dstlen + 2);
2128 char * pIn = src.data();
2129 char * pOut = dst.data();
2131 strncpy(pIn, text.c_str(), srclen);
2133 size_t len = iconv(conv, &pIn, &srclen, &pOut, &dstlen);
2134 if (len != (
size_t) -1)
2146 int orgerrno = errno;
2155int get_encoding (
const char * str, std::string & encoding)
2157 DetectObj *obj = detect_obj_init();
2165#ifndef CHARDET_BINARY_SAFE
2167 switch (detect (str, &obj))
2170 switch (detect_r (str, strlen (str), &obj))
2173 case CHARDET_OUT_OF_MEMORY :
2175 detect_obj_free (&obj);
2177 case CHARDET_NULL_OBJECT :
2191 encoding = obj->encoding;
2192 detect_obj_free (&obj);
2197int read_file(
const std::string & path, std::string & result)
2199 constexpr std::array<char, 3> UTF_8_BOM = {
'\xEF',
'\xBB',
'\xBF' };
2200 constexpr std::array<char, 2> UTF_16_BE_BOM = {
'\xFE',
'\xFF' };
2201 constexpr std::array<char, 2> UTF_16_LE_BOM = {
'\xFF',
'\xFE' };
2202 constexpr std::array<char, 4> UTF_32_BE_BOM = {
'\x00',
'\x00',
'\xFE',
'\xFF' };
2203 constexpr std::array<char, 4> UTF_32_LE_BOM = {
'\xFF',
'\xFE',
'\x00',
'\x00' };
2211 ifs.open(path, std::ios::binary);
2228 std::array<char, 4> BOM;
2229 ifs.read(BOM.data(), BOM.size());
2234 if (!memcmp(BOM.data(), UTF_32_LE_BOM.data(), UTF_32_LE_BOM.size()))
2238 ifs.seekg(UTF_32_LE_BOM.size());
2240 else if (!memcmp(BOM.data(), UTF_32_BE_BOM.data(), UTF_32_BE_BOM.size()))
2244 ifs.seekg(UTF_32_BE_BOM.size());
2246 else if (!memcmp(BOM.data(), UTF_16_LE_BOM.data(), UTF_16_LE_BOM.size()))
2250 ifs.seekg(UTF_16_LE_BOM.size());
2252 else if (!memcmp(BOM.data(), UTF_16_BE_BOM.data(), UTF_16_BE_BOM.size()))
2256 ifs.seekg(UTF_16_BE_BOM.size());
2258 else if (!memcmp(BOM.data(), UTF_8_BOM.data(), UTF_8_BOM.size()))
2262 ifs.seekg(UTF_8_BOM.size());
2278 for (
char16_t ch; ifs.read((
char*)&ch,
sizeof(ch));)
2280#if __BYTE_ORDER == __BIG_ENDIAN
2281 in.push_back((
char16_t)__builtin_bswap16(ch));
2287 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,
char16_t> utfconv;
2288 result = utfconv.to_bytes(in);
2296 for (
char16_t ch; ifs.read((
char*)&ch,
sizeof(ch));)
2298#if __BYTE_ORDER == __BIG_ENDIAN
2301 in.push_back((
char16_t)__builtin_bswap16(ch));
2305 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,
char16_t> utfconv;
2306 result = utfconv.to_bytes(in);
2315 for (
char32_t ch; ifs.read((
char*)&ch,
sizeof(ch));)
2317#if __BYTE_ORDER == __BIG_ENDIAN
2318 in.push_back((
char32_t)__builtin_bswap32(ch));
2324 std::wstring_convert<std::codecvt_utf8<char32_t>,
char32_t> utfconv;
2325 result = utfconv.to_bytes(in);
2334 for (
char32_t ch; ifs.read((
char*)&ch,
sizeof(ch));)
2336#if __BYTE_ORDER == __BIG_ENDIAN
2339 in.push_back((
char32_t)__builtin_bswap32(ch));
2343 std::wstring_convert<std::codecvt_utf8<char32_t>,
char32_t> utfconv;
2344 result = utfconv.to_bytes(in);
2350 std::stringstream ss;
2358 std::stringstream ss;
2363 std::string encoding_name;
2370 if (encoding_name !=
"UTF-8")
2373 res =
to_utf8(result, encoding_name);
2382 res =
static_cast<int>(encoding);
2384 catch (
const std::system_error& e)
2397#if defined __x86_64__ || !defined __USE_FILE_OFFSET64
2398 st->st_size =
static_cast<__off_t
>(size);
2400 st->st_size =
static_cast<__off64_t
>(size);
2402 st->st_blocks = (st->st_size + 512 - 1) / 512;
2409 std::ifstream
const in_stream(
"/proc/self/cgroup");
2410 std::stringstream buffer;
2411 buffer << in_stream.rdbuf();
2412 auto const& content_as_string = buffer.str();
2413 return std::string::npos != content_as_string.find(
"/docker");
2415 catch (std::exception
const& ex)
2417 std::fprintf(stderr,
"detect_docker(): Unable check if running in docker or not, exception: %s.", ex.what());
2451 return (codec_id != AV_CODEC_ID_DVD_SUBTITLE && codec_id != AV_CODEC_ID_DVB_SUBTITLE && codec_id != AV_CODEC_ID_HDMV_PGS_SUBTITLE);
2454int get_audio_props(AVFormatContext *format_ctx,
int *channels,
int *samplerate)
2461#if LAVU_DEP_OLD_CHANNEL_LAYOUT
2462 *channels = format_ctx->streams[ret]->codecpar->ch_layout.nb_channels;
2464 *channels = format_ctx->streams[ret]->codecpar->channels;
2466 *samplerate = format_ctx->streams[ret]->codecpar->sample_rate;
2476 const std::vector<std::string> charlist {
"\\",
"+",
"*",
"?",
"^",
"$",
"(",
")",
"[",
"]",
"{",
"}",
"|"};
2478 for (
const std::string & ch : charlist)
2496 auto is_match = [ext](
const std::string & regex_string) {
return (fnmatch(regex_string.c_str(), ext.c_str(), 0) == 0); };
2518 auto is_match = [ext](
const std::string & regex_string) {
return (fnmatch(regex_string.c_str(), ext.c_str(), 0) == 0); };
2526 void * tmp = __atomic_exchange_n(p,
nullptr, __ATOMIC_RELEASE);
2535 std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
2540 std::this_thread::sleep_for(std::chrono::microseconds(microseconds));
2545 std::this_thread::sleep_for(std::chrono::nanoseconds(nanoseconds));
bool check_ignore(size_t size, size_t offset)
For use with win_smb_fix=1: Check if this an illegal access offset by Windows.
void nssleep(int nanoseconds)
Sleep for specified time.
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.
int get_encoding(const char *str, std::string &encoding)
Try to detect the encoding of str. This is relatively realiable, but may be wrong.
const std::string & remove_path(std::string *filepath)
Remove path from filename. Handy basename alternative.
std::string format_duration(int64_t value, uint32_t fracs)
Format a time in format HH:MM:SS.fract.
void exepath(std::string *path)
Path to FFmpegfs binary.
static int is_device(__attribute__((unused)) const AVClass *avclass)
Check if class is a FMmpeg device.
void ussleep(int microseconds)
Sleep for specified time.
int is_mount(const std::string &path)
Check if path is a mount.
std::string & trim(std::string &s)
trim from both ends
int mktree(const std::string &path, mode_t mode)
Make directory tree.
int nocasecompare(const std::string &lhs, const std::string &rhs)
nocasecompare to make std::string find operations case insensitive
void make_upper(std::string *input)
Convert string to upper case.
int read_file(const std::string &path, std::string &result)
Read text file and return in UTF-8 format, no matter in which encoding the input file is....
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.
std::string get_filetype_text(FILETYPE filetype)
Convert FILETYPE enum to human readable text.
bool is_blocked(const std::string &filename)
Check if filename should be hidden from output path.
std::map< const std::string, const FILETYPE, comp > FILETYPE_MAP
Map of file type. One entry per supported type.
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.
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.
void tempdir(std::string &path)
Get temporary directory.
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 ...
bool is_text_codec(AVCodecID codec_id)
Check if subtitle codec is a text or graphical codec.
const char * get_media_type_string(enum AVMediaType media_type)
av_get_media_type_string is missing, so we provide our own.
const std::string & regex_escape(std::string *str)
Escape characters that are meaningful to regexp.
std::string format_result_size(size_t size_resulting, size_t size_predicted)
Format size of transcoded file including difference between predicted and resulting size.
std::string & rtrim(std::string &s)
trim from end
const char * hwdevice_get_type_name(AVHWDeviceType dev_type)
int64_t ffmpeg_rescale_q_rnd(int64_t ts, const AVRational &timebase_in, const AVRational &timebase_out)
Convert a FFmpeg time from in timebase to out timebase with rounding.
int supports_albumart(FILETYPE filetype)
Check if file type supports album arts.
FILETYPE get_filetype(const std::string &desttype)
Get the FFmpegfs filetype, desttype must be one of FFmpeg's "official" short names for formats.
#define PRINT_LIB_INFO(libname, LIBNAME)
Print info about a FFmpeg library.
int show_caps(int device_only)
Lists all supported codecs and devices.
size_t get_disk_free(std::string &path)
Get free disk space.
#define X(name)
Convert macro to string.
std::string fourcc_make_string(std::string *buf, uint32_t fourcc)
static const FILETYPE_MAP filetype_map
std::shared_ptr< char[]> new_strdup(const std::string &str)
strdup() variant taking a std::string as input.
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 make_filename(uint32_t file_no, const std::string &fileext)
Make a file name from file number and file extension.
std::string format_bitrate(BITRATE value)
Format a bit rate.
std::string & ltrim(std::string &s)
trim from start
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.
bool detect_docker()
Detect if we are running under Docker.
void make_lower(std::string *input)
Convert string to lower case.
const std::string & remove_sep(std::string *path)
Remove / from the path.
const std::string & remove_ext(std::string *filepath)
Remove extension from filename.
void save_free(void **p)
Savely free memory: Pointer will be set to nullptr before it is actually freed.
static std::string ffmpeg_libinfo(bool lib_exists, __attribute__((unused)) unsigned int version, __attribute__((unused)) const char *cfg, int version_minor, int version_major, int version_micro, const char *libname)
Get FFmpeg library info.
const std::string & append_ext(std::string *filepath, const std::string &ext)
Append extension to filename. If ext is the same as.
std::string format_result_size_ex(size_t size_resulting, size_t size_predicted)
Format size of transcoded file including difference between predicted and resulting size.
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.
void mssleep(int milliseconds)
Sleep for specified time.
void append_basepath(std::string *origpath, const char *path)
Translate file names from FUSE to the original absolute path.
bool file_exists(const std::string &filename)
Check if file exists.
static void print_fps(double d, const char *postfix)
Print frames per second.
int print_stream_info(const AVStream *stream)
Print info about an AVStream.
std::string format_size(uint64_t value)
Format size.
void stat_set_size(struct stat *st, size_t size)
Properly fill in all size related members in stat struct.
std::vector< std::string > split(const std::string &input, const std::string ®ex)
Split string into an array delimited by a regular expression.
void init_id3v1(ID3v1 *id3v1)
Initialise ID3v1 tag.
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.
std::string format_size_ex(uint64_t value)
Format size.
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.
int to_utf8(std::string &text, const std::string &encoding)
Convert almost any encoding to UTF-8. To get a list of all possible encodings run "iconv --list".
std::string format_number(int64_t value)
Format numeric value.
FILETYPE get_filetype_from_list(const std::string &desttypelist)
Get the FFmpegfs filetype, desttypelist must be a comma separated list of FFmpeg's "official" short n...
int64_t ffmpeg_rescale_q(int64_t ts, const AVRational &timebase_in, const AVRational &timebase_out)
Convert a FFmpeg time from in timebase to outtime base.
std::string ffmpeg_geterror(int errnum)
Get FFmpeg error string for errnum. Internally calls av_strerror().
#define BITRATE
For FFmpeg bit rate is an int.
#define AV_ROUND_PASS_MINMAX
@ UTF8_BOM
UTF-8 with bottom mark.
@ UTF32BE_BOM
UTF-16 big-endian with bottom mark.
@ UTF16BE_BOM
UTF-16 big-endian with bottom mark.
@ UTF32LE_BOM
UTF-16 little-endian with bottom mark.
@ ASCII
Some sort of ASCII encoding.
@ UTF16LE_BOM
UTF-16 little-endian with bottom mark.
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.
const std::string & strsprintf(std::string *str, const std::string &format, Args ... args)
Format a std::string sprintf-like.
@ FMT_F16
16 bit floating point
@ FMT_F32
32 bit floating point
@ FMT_F24
24 bit floating point
@ FMT_DONTCARE
Don't care, leave to FFmpegfs to choose.
@ FMT_F64
64 bit floating point
#define INVALID_STREAM
Denote an invalid stream.
FFMPEGFS_PARAMS params
FFmpegfs command line parameters.
std::string get_sampleformat_text(SAMPLE_FMT sample_fmt)
Convert SAMPLE_FMT enum to human readable text.
std::string get_video_codec_text(AVCodecID video_codec)
Convert AVCodecID enum for video codec to human readable text.
std::string get_audio_codec_text(AVCodecID audio_codec)
Convert AVCodecID enum for audio codec to human readable text.
Main include for FFmpegfs project.
SAMPLE_FMT m_sample_fmt
Sample format.
AVCodecID m_video_codec
Either AV_CODEC_ID_NONE for default, or a user selected codec.
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...
AVCodecID m_audio_codec
Either AV_CODEC_ID_NONE for default, or a user selected codec.
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 ...
std::string m_basepath
Base path: Files from this directory (including all sub directories) will be mapped to m_mountpath.
char m_title_no
Title number.
char m_padding
Padding byte, must be '\0'.
std::array< char, 3 > m_tag
Contains "TAG".
char m_genre
Type of music.