From f69aa8cf89f7c8bc413d6cbb9eff899750e4a373 Mon Sep 17 00:00:00 2001 From: Christian Feldmann Date: Tue, 26 Sep 2023 22:06:47 +0200 Subject: [PATCH 1/7] Rework ffmpeg info return --- YUViewLib/src/ffmpeg/FFmpegVersionHandler.cpp | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/YUViewLib/src/ffmpeg/FFmpegVersionHandler.cpp b/YUViewLib/src/ffmpeg/FFmpegVersionHandler.cpp index 7576720ba..02ea5c38c 100644 --- a/YUViewLib/src/ffmpeg/FFmpegVersionHandler.cpp +++ b/YUViewLib/src/ffmpeg/FFmpegVersionHandler.cpp @@ -207,27 +207,21 @@ auto SupportedLibraryVersionCombinations = { //} // -QString FFmpegVersionHandler::getLibVersionString() const -{ - QString s; - s += QString("avUtil %1.%2.%3 ") - .arg(libVersion.avutil.major) - .arg(libVersion.avutil.minor.value_or(0)) - .arg(libVersion.avutil.micro.value_or(0)); - s += QString("avFormat %1.%2.%3 ") - .arg(libVersion.avformat.major) - .arg(libVersion.avformat.minor.value_or(0)) - .arg(libVersion.avformat.micro.value_or(0)); - s += QString("avCodec %1.%2.%3 ") - .arg(libVersion.avcodec.major) - .arg(libVersion.avcodec.minor.value_or(0)) - .arg(libVersion.avcodec.micro.value_or(0)); - s += QString("swresample %1.%2.%3") - .arg(libVersion.swresample.major) - .arg(libVersion.swresample.minor.value_or(0)) - .arg(libVersion.swresample.micro.value_or(0)); - - return s; +std::string FFmpegVersionHandler::getLibVersionString() const +{ + std::ostringstream stream; + + auto addVersion = [&stream](const char *name, const Version &version) { + stream << name << version.major << "." << version.minor.value_or(0) << "." + << version.micro.value_or(0); + }; + + addVersion("avUtil", libVersion.avutil); + addVersion("avFormat", libVersion.avformat); + addVersion("avCodec", libVersion.avcodec); + addVersion("swresample", libVersion.swresample); + + return stream.str(); } AVCodecIDWrapper FFmpegVersionHandler::getCodecIDWrapper(AVCodecID id) From 3f1c7c7d869adf97a5f3bea32c4cdc50ab4a1d8c Mon Sep 17 00:00:00 2001 From: Christian Feldmann Date: Tue, 26 Sep 2023 22:12:01 +0200 Subject: [PATCH 2/7] Update settings dialog --- YUViewLib/ui/settingsDialog.ui | 93 ++++++---------------------------- 1 file changed, 15 insertions(+), 78 deletions(-) diff --git a/YUViewLib/ui/settingsDialog.ui b/YUViewLib/ui/settingsDialog.ui index 4d6545017..d433e3890 100644 --- a/YUViewLib/ui/settingsDialog.ui +++ b/YUViewLib/ui/settingsDialog.ui @@ -17,7 +17,7 @@ - 0 + 2 @@ -1202,80 +1202,13 @@ Specify the individual FFmpeg libraries to use. These will always be tried first. - FFmpeg Libraries + FFmpeg Path - - - - libAVCodec - - - - - - - libAVFormat - - - - - - - libAVUtil - - - - - - - libSWResample - - - - - - - The libAVFormat library to use. - - - The libAVFormat library to use. - - - true - - - - - - - The libAVCodec library to use. - - - The libAVCodec library to use. - - - true - - - - - - - The libSWResample library to use. - - - The libSWResample library to use. - - - true - - - - + The libAVUtil library to use. @@ -1287,10 +1220,17 @@ + + + + FFmpeg Path + + + - + 0 @@ -1313,7 +1253,7 @@ - + 0 @@ -1416,12 +1356,9 @@ lineEditDecoderPath pushButtonDecoderSelectPath pushButtonDecoderClearPath - lineEditAVUtil - lineEditSWResample - lineEditAVCodec - lineEditAVFormat - pushButtonFFMpegSelectFile - pushButtonFFMpegClearFile + lineEditFFmpegPath + pushButtonFFMpegSelectPath + pushButtonFFMpegClearPath pushButtonSave pushButtonCancel From 8239cb186cc728af04b328afe9ddd85ecfa3c88b Mon Sep 17 00:00:00 2001 From: Christian Feldmann Date: Thu, 28 Sep 2023 21:49:59 +0200 Subject: [PATCH 3/7] Many more refactorings --- YUViewLib/src/common/FileInfo.cpp | 18 +- YUViewLib/src/common/FileInfo.h | 3 +- YUViewLib/src/decoder/decoderFFmpeg.cpp | 43 +++-- .../src/ffmpeg/AVCodecContextWrapper.cpp | 16 +- YUViewLib/src/ffmpeg/AVCodecContextWrapper.h | 4 +- YUViewLib/src/ffmpeg/AVCodecIDWrapper.h | 15 +- .../src/ffmpeg/AVCodecParametersWrapper.cpp | 63 ++++--- .../src/ffmpeg/AVCodecParametersWrapper.h | 4 +- YUViewLib/src/ffmpeg/AVCodecWrapper.cpp | 36 +++- YUViewLib/src/ffmpeg/AVCodecWrapper.h | 36 ++-- .../src/ffmpeg/AVFormatContextWrapper.cpp | 32 ++-- YUViewLib/src/ffmpeg/AVFormatContextWrapper.h | 4 +- .../src/ffmpeg/AVFrameSideDataWrapper.cpp | 60 +++---- YUViewLib/src/ffmpeg/AVFrameSideDataWrapper.h | 19 +-- YUViewLib/src/ffmpeg/AVFrameWrapper.cpp | 30 ++-- YUViewLib/src/ffmpeg/AVFrameWrapper.h | 7 +- YUViewLib/src/ffmpeg/AVInputFormatWrapper.cpp | 34 ++-- YUViewLib/src/ffmpeg/AVInputFormatWrapper.h | 26 ++- YUViewLib/src/ffmpeg/AVPacketWrapper.cpp | 54 +++--- YUViewLib/src/ffmpeg/AVPacketWrapper.h | 4 +- .../src/ffmpeg/AVPixFmtDescriptorWrapper.cpp | 30 ++-- .../src/ffmpeg/AVPixFmtDescriptorWrapper.h | 8 +- YUViewLib/src/ffmpeg/AVStreamWrapper.cpp | 44 ++--- YUViewLib/src/ffmpeg/AVStreamWrapper.h | 6 +- YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.h | 54 +++++- .../src/ffmpeg/FFmpegLibraryFunctions.cpp | 44 +++-- YUViewLib/src/ffmpeg/FFmpegLibraryFunctions.h | 13 +- YUViewLib/src/ffmpeg/FFmpegVersionHandler.cpp | 160 +++++++----------- YUViewLib/src/ffmpeg/FFmpegVersionHandler.h | 8 +- YUViewLib/src/ffmpeg/LibraryLoader.h | 2 + ...tionVectorWrapper.cpp => MotionVector.cpp} | 90 +++++----- ...AVMotionVectorWrapper.h => MotionVector.h} | 13 +- .../src/filesource/FileSourceFFmpegFile.cpp | 2 +- .../src/filesource/FileSourceFFmpegFile.h | 3 +- .../src/parser/AVFormat/ParserAVFormat.cpp | 3 +- .../playlistItemCompressedVideo.cpp | 5 +- 36 files changed, 513 insertions(+), 480 deletions(-) rename YUViewLib/src/ffmpeg/{AVMotionVectorWrapper.cpp => MotionVector.cpp} (50%) rename YUViewLib/src/ffmpeg/{AVMotionVectorWrapper.h => MotionVector.h} (85%) diff --git a/YUViewLib/src/common/FileInfo.cpp b/YUViewLib/src/common/FileInfo.cpp index 197915d4d..8306f3907 100644 --- a/YUViewLib/src/common/FileInfo.cpp +++ b/YUViewLib/src/common/FileInfo.cpp @@ -32,20 +32,18 @@ #include "FileInfo.h" -std::vector InfoItem::fromFFmpegLibraryPaths(const FFmpeg::LibraryPaths &paths) +std::vector +InfoItem::fromFFmpegLibrariesInfo(const std::vector &librariesInfo) { std::vector items; - auto addItem = [&items](QString name, const std::filesystem::path &path) { - const auto text = QString::fromStdString(path.filename().string()); - const auto tooltip = QString::fromStdString(path.string()); + for (const auto &libInfo : librariesInfo) + { + const auto name = QString::fromStdString(libInfo.name); + const auto text = QString::fromStdString(libInfo.path.filename().string()); + const auto tooltip = QString::fromStdString(libInfo.path.string()); items.push_back(InfoItem(name, text, tooltip)); - }; - - addItem("AVFormat", paths.avFormat); - addItem("AVCodec", paths.avCodec); - addItem("AVUtil", paths.avUtil); - addItem("SWResample", paths.swResample); + } return items; } diff --git a/YUViewLib/src/common/FileInfo.h b/YUViewLib/src/common/FileInfo.h index a2831dbbf..c6aa76dcb 100644 --- a/YUViewLib/src/common/FileInfo.h +++ b/YUViewLib/src/common/FileInfo.h @@ -55,7 +55,8 @@ struct InfoItem { } - static std::vector fromFFmpegLibraryPaths(const FFmpeg::LibraryPaths &paths); + static std::vector + fromFFmpegLibrariesInfo(const std::vector &librariesInfo); QString name{}; QString text{}; diff --git a/YUViewLib/src/decoder/decoderFFmpeg.cpp b/YUViewLib/src/decoder/decoderFFmpeg.cpp index 71a835d5e..902ec6139 100644 --- a/YUViewLib/src/decoder/decoderFFmpeg.cpp +++ b/YUViewLib/src/decoder/decoderFFmpeg.cpp @@ -104,7 +104,7 @@ decoderFFmpeg::decoderFFmpeg(FFmpeg::AVCodecParametersWrapper codecpar, bool cac return; auto codecID = this->ff.getCodecIDWrapper(codecpar.getCodecID()); - this->codecName = codecID.getCodecName(); + this->codecName = QString::fromStdString(codecID.getCodecName()); if (!this->createDecoder(codecID, codecpar)) { this->setError("Error creating the needed decoder."); @@ -269,29 +269,25 @@ void decoderFFmpeg::copyCurImageToBuffer() void decoderFFmpeg::cacheCurStatistics() { - // Copy the statistics of the current frame to the buffer DEBUG_FFMPEG("decoderFFmpeg::cacheCurStatistics"); - // Try to get the motion information - auto sideData = this->ff.getSideData(frame, FFmpeg::AV_FRAME_DATA_MOTION_VECTORS); - if (sideData) + const auto sideData = this->ff.getSideData(frame, FFmpeg::AV_FRAME_DATA_MOTION_VECTORS); + if (!sideData) + return; + + const auto motionVectors = sideData.getMotionVectors(); + for (const auto &motionVector : motionVectors) { - const auto nrMVs = sideData.getNumberMotionVectors(); - for (size_t i = 0; i < nrMVs; i++) - { - auto mvs = sideData.getMotionVector(unsigned(i)); - - // dst marks the center of the current block so the block position is: - const int blockX = mvs.dst_x - mvs.w / 2; - const int blockY = mvs.dst_y - mvs.h / 2; - const int16_t mvX = mvs.dst_x - mvs.src_x; - const int16_t mvY = mvs.dst_y - mvs.src_y; - - this->statisticsData->at(mvs.source < 0 ? 0 : 1) - .addBlockValue(blockX, blockY, mvs.w, mvs.h, (int)mvs.source); - this->statisticsData->at(mvs.source < 0 ? 2 : 3) - .addBlockVector(blockX, blockY, mvs.w, mvs.h, mvX, mvY); - } + // dst marks the center of the current block so the block position is: + const int blockX = motionVector.dst_x - motionVector.w / 2; + const int blockY = motionVector.dst_y - motionVector.h / 2; + const int16_t mvX = motionVector.dst_x - motionVector.src_x; + const int16_t mvY = motionVector.dst_y - motionVector.src_y; + + this->statisticsData->at(motionVector.source < 0 ? 0 : 1) + .addBlockValue(blockX, blockY, motionVector.w, motionVector.h, (int)motionVector.source); + this->statisticsData->at(motionVector.source < 0 ? 2 : 3) + .addBlockVector(blockX, blockY, motionVector.w, motionVector.h, mvX, mvY); } } @@ -321,8 +317,7 @@ bool decoderFFmpeg::pushData(QByteArray &data) std::vector decoderFFmpeg::getDecoderInfo() const { - const auto libraryPaths = this->ff.getLibraryPaths(); - return InfoItem::fromFFmpegLibraryPaths(libraryPaths); + return InfoItem::fromFFmpegLibrariesInfo(this->ff.getLibrariesInfo()); } bool decoderFFmpeg::pushAVPacket(FFmpeg::AVPacketWrapper &pkt) @@ -450,7 +445,7 @@ bool decoderFFmpeg::createDecoder(FFmpeg::AVCodecIDWrapper codecID, this->videoCodec = this->ff.findDecoder(codecID); if (!this->videoCodec) return this->setErrorB(QStringLiteral("Could not find a video decoder for the given codec ") + - codecID.getCodecName()); + QString::fromStdString(codecID.getCodecName())); if (this->decCtx) return this->setErrorB(QStringLiteral("Decoder context already allocated.")); diff --git a/YUViewLib/src/ffmpeg/AVCodecContextWrapper.cpp b/YUViewLib/src/ffmpeg/AVCodecContextWrapper.cpp index dea86930a..6b7be6559 100644 --- a/YUViewLib/src/ffmpeg/AVCodecContextWrapper.cpp +++ b/YUViewLib/src/ffmpeg/AVCodecContextWrapper.cpp @@ -419,10 +419,11 @@ AVCodecContextWrapper::AVCodecContextWrapper() this->codec = nullptr; } -AVCodecContextWrapper::AVCodecContextWrapper(AVCodecContext *c, LibraryVersion v) +AVCodecContextWrapper::AVCodecContextWrapper(AVCodecContext * c, + const LibraryVersions &libraryVersions) { - this->codec = c; - this->libVer = v; + this->codec = c; + this->libraryVersions = libraryVersions; this->update(); } @@ -478,7 +479,7 @@ void AVCodecContextWrapper::update() if (this->codec == nullptr) return; - if (this->libVer.avcodec.major == 56) + if (this->libraryVersions.avcodec.major == 56) { auto p = reinterpret_cast(this->codec); this->codec_type = p->codec_type; @@ -562,7 +563,7 @@ void AVCodecContextWrapper::update() this->color_range = p->color_range; this->chroma_sample_location = p->chroma_sample_location; } - else if (libVer.avcodec.major == 57) + else if (this->libraryVersions.avcodec.major == 57) { auto p = reinterpret_cast(this->codec); this->codec_type = p->codec_type; @@ -646,7 +647,7 @@ void AVCodecContextWrapper::update() this->color_range = p->color_range; this->chroma_sample_location = p->chroma_sample_location; } - else if (libVer.avcodec.major == 58) + else if (this->libraryVersions.avcodec.major == 58) { auto p = reinterpret_cast(this->codec); this->codec_type = p->codec_type; @@ -730,7 +731,8 @@ void AVCodecContextWrapper::update() this->color_range = p->color_range; this->chroma_sample_location = p->chroma_sample_location; } - else if (libVer.avcodec.major == 59 || libVer.avcodec.major == 60) + else if (this->libraryVersions.avcodec.major == 59 || // + this->libraryVersions.avcodec.major == 60) { auto p = reinterpret_cast(this->codec); this->codec_type = p->codec_type; diff --git a/YUViewLib/src/ffmpeg/AVCodecContextWrapper.h b/YUViewLib/src/ffmpeg/AVCodecContextWrapper.h index 760f6a171..2c7422010 100644 --- a/YUViewLib/src/ffmpeg/AVCodecContextWrapper.h +++ b/YUViewLib/src/ffmpeg/AVCodecContextWrapper.h @@ -42,7 +42,7 @@ class AVCodecContextWrapper { public: AVCodecContextWrapper(); - AVCodecContextWrapper(AVCodecContext *c, LibraryVersion v); + AVCodecContextWrapper(AVCodecContext *c, const LibraryVersions &libraryVersions); explicit operator bool() const { return this->codec != nullptr; }; @@ -142,7 +142,7 @@ class AVCodecContextWrapper AVChromaLocation chroma_sample_location{}; AVCodecContext *codec{}; - LibraryVersion libVer{}; + LibraryVersions libraryVersions{}; }; } // namespace FFmpeg diff --git a/YUViewLib/src/ffmpeg/AVCodecIDWrapper.h b/YUViewLib/src/ffmpeg/AVCodecIDWrapper.h index 4502c73e8..66c7a1341 100644 --- a/YUViewLib/src/ffmpeg/AVCodecIDWrapper.h +++ b/YUViewLib/src/ffmpeg/AVCodecIDWrapper.h @@ -41,10 +41,13 @@ class AVCodecIDWrapper { public: AVCodecIDWrapper() {} - AVCodecIDWrapper(AVCodecID codecID, QString codecName) : codecID(codecID), codecName(codecName) {} + AVCodecIDWrapper(AVCodecID codecID, std::string codecName) + : codecID(codecID), codecName(codecName) + { + } - QString getCodecName() const { return this->codecName; } - AVCodecID getCodecID() const { return this->codecID; } + std::string getCodecName() const { return this->codecName; } + AVCodecID getCodecID() const { return this->codecID; } void setCodecID(AVCodecID id) { this->codecID = id; } @@ -58,15 +61,15 @@ class AVCodecIDWrapper bool isNone() const { - return this->codecName.isEmpty() || this->codecName == "unknown_codec" || + return this->codecName.empty() || this->codecName == "unknown_codec" || this->codecName == "none"; } bool operator==(const AVCodecIDWrapper &a) const { return codecID == a.codecID; } private: - AVCodecID codecID{AV_CODEC_ID_NONE}; - QString codecName; + AVCodecID codecID{AV_CODEC_ID_NONE}; + std::string codecName; }; } // namespace FFmpeg diff --git a/YUViewLib/src/ffmpeg/AVCodecParametersWrapper.cpp b/YUViewLib/src/ffmpeg/AVCodecParametersWrapper.cpp index 56d0c943e..b38dc0e45 100644 --- a/YUViewLib/src/ffmpeg/AVCodecParametersWrapper.cpp +++ b/YUViewLib/src/ffmpeg/AVCodecParametersWrapper.cpp @@ -69,10 +69,11 @@ typedef struct AVCodecParameters_57_58_59_60 } // namespace -AVCodecParametersWrapper::AVCodecParametersWrapper(AVCodecParameters *p, LibraryVersion v) +AVCodecParametersWrapper::AVCodecParametersWrapper(AVCodecParameters * p, + const LibraryVersions &libraryVersionsv) { - this->param = p; - this->libVer = v; + this->param = p; + this->libraryVersions = libraryVersions; this->update(); } @@ -229,8 +230,10 @@ QStringPairList AVCodecParametersWrapper::getInfoText() void AVCodecParametersWrapper::setClearValues() { - if (this->libVer.avformat.major == 57 || this->libVer.avformat.major == 58 || - this->libVer.avformat.major == 59 || this->libVer.avformat.major == 60) + if (this->libraryVersions.avformat.major == 57 || // + this->libraryVersions.avformat.major == 58 || // + this->libraryVersions.avformat.major == 59 || // + this->libraryVersions.avformat.major == 60) { auto p = reinterpret_cast(this->param); p->codec_type = AVMEDIA_TYPE_UNKNOWN; @@ -265,8 +268,10 @@ void AVCodecParametersWrapper::setClearValues() void AVCodecParametersWrapper::setAVMediaType(AVMediaType type) { - if (this->libVer.avformat.major == 57 || this->libVer.avformat.major == 58 || - this->libVer.avformat.major == 59 || this->libVer.avformat.major == 60) + if (this->libraryVersions.avformat.major == 57 || // + this->libraryVersions.avformat.major == 58 || // + this->libraryVersions.avformat.major == 59 || // + this->libraryVersions.avformat.major == 60) { auto p = reinterpret_cast(this->param); p->codec_type = type; @@ -276,8 +281,10 @@ void AVCodecParametersWrapper::setAVMediaType(AVMediaType type) void AVCodecParametersWrapper::setAVCodecID(AVCodecID id) { - if (this->libVer.avformat.major == 57 || this->libVer.avformat.major == 58 || - this->libVer.avformat.major == 59 || this->libVer.avformat.major == 60) + if (this->libraryVersions.avformat.major == 57 || // + this->libraryVersions.avformat.major == 58 || // + this->libraryVersions.avformat.major == 59 || // + this->libraryVersions.avformat.major == 60) { auto p = reinterpret_cast(this->param); p->codec_id = id; @@ -287,8 +294,10 @@ void AVCodecParametersWrapper::setAVCodecID(AVCodecID id) void AVCodecParametersWrapper::setExtradata(QByteArray data) { - if (this->libVer.avformat.major == 57 || this->libVer.avformat.major == 58 || - this->libVer.avformat.major == 59 || this->libVer.avformat.major == 60) + if (this->libraryVersions.avformat.major == 57 || // + this->libraryVersions.avformat.major == 58 || // + this->libraryVersions.avformat.major == 59 || // + this->libraryVersions.avformat.major == 60) { this->extradata = data; auto p = reinterpret_cast(this->param); @@ -299,8 +308,10 @@ void AVCodecParametersWrapper::setExtradata(QByteArray data) void AVCodecParametersWrapper::setSize(Size size) { - if (this->libVer.avformat.major == 57 || this->libVer.avformat.major == 58 || - this->libVer.avformat.major == 59 || this->libVer.avformat.major == 60) + if (this->libraryVersions.avformat.major == 57 || // + this->libraryVersions.avformat.major == 58 || // + this->libraryVersions.avformat.major == 59 || // + this->libraryVersions.avformat.major == 60) { auto p = reinterpret_cast(this->param); p->width = size.width; @@ -312,8 +323,10 @@ void AVCodecParametersWrapper::setSize(Size size) void AVCodecParametersWrapper::setAVPixelFormat(AVPixelFormat format) { - if (this->libVer.avformat.major == 57 || this->libVer.avformat.major == 58 || - this->libVer.avformat.major == 59 || this->libVer.avformat.major == 60) + if (this->libraryVersions.avformat.major == 57 || // + this->libraryVersions.avformat.major == 58 || // + this->libraryVersions.avformat.major == 59 || // + this->libraryVersions.avformat.major == 60) { auto p = reinterpret_cast(this->param); p->format = format; @@ -323,8 +336,10 @@ void AVCodecParametersWrapper::setAVPixelFormat(AVPixelFormat format) void AVCodecParametersWrapper::setProfileLevel(int profile, int level) { - if (this->libVer.avformat.major == 57 || this->libVer.avformat.major == 58 || - this->libVer.avformat.major == 59 || this->libVer.avformat.major == 60) + if (this->libraryVersions.avformat.major == 57 || // + this->libraryVersions.avformat.major == 58 || // + this->libraryVersions.avformat.major == 59 || // + this->libraryVersions.avformat.major == 60) { auto p = reinterpret_cast(this->param); p->profile = profile; @@ -336,8 +351,10 @@ void AVCodecParametersWrapper::setProfileLevel(int profile, int level) void AVCodecParametersWrapper::setSampleAspectRatio(int num, int den) { - if (this->libVer.avformat.major == 57 || this->libVer.avformat.major == 58 || - this->libVer.avformat.major == 59 || this->libVer.avformat.major == 60) + if (this->libraryVersions.avformat.major == 57 || // + this->libraryVersions.avformat.major == 58 || // + this->libraryVersions.avformat.major == 59 || // + this->libraryVersions.avformat.major == 60) { auto p = reinterpret_cast(param); AVRational ratio; @@ -353,13 +370,15 @@ void AVCodecParametersWrapper::update() if (this->param == nullptr) return; - if (this->libVer.avformat.major == 56) + if (this->libraryVersions.avformat.major == 56) { // This data structure does not exist in avformat major version 56. this->param = nullptr; } - else if (this->libVer.avformat.major == 57 || this->libVer.avformat.major == 58 || - this->libVer.avformat.major == 59 || this->libVer.avformat.major == 60) + else if (this->libraryVersions.avformat.major == 57 || // + this->libraryVersions.avformat.major == 58 || // + this->libraryVersions.avformat.major == 59 || // + this->libraryVersions.avformat.major == 60) { auto p = reinterpret_cast(this->param); diff --git a/YUViewLib/src/ffmpeg/AVCodecParametersWrapper.h b/YUViewLib/src/ffmpeg/AVCodecParametersWrapper.h index 3542e11bb..365803bd8 100644 --- a/YUViewLib/src/ffmpeg/AVCodecParametersWrapper.h +++ b/YUViewLib/src/ffmpeg/AVCodecParametersWrapper.h @@ -41,7 +41,7 @@ class AVCodecParametersWrapper { public: AVCodecParametersWrapper() = default; - AVCodecParametersWrapper(AVCodecParameters *p, LibraryVersion v); + AVCodecParametersWrapper(AVCodecParameters *p, const LibraryVersions &libraryVersions); explicit operator bool() const { return this->param != nullptr; } QStringPairList getInfoText(); @@ -93,7 +93,7 @@ class AVCodecParametersWrapper int video_delay{}; AVCodecParameters *param{}; - LibraryVersion libVer{}; + LibraryVersions libraryVersions{}; }; } // namespace FFmpeg diff --git a/YUViewLib/src/ffmpeg/AVCodecWrapper.cpp b/YUViewLib/src/ffmpeg/AVCodecWrapper.cpp index 2d826e43c..70192f2d9 100644 --- a/YUViewLib/src/ffmpeg/AVCodecWrapper.cpp +++ b/YUViewLib/src/ffmpeg/AVCodecWrapper.cpp @@ -90,16 +90,40 @@ template std::vector convertRawListToVec(const T *rawValues, T t } // namespace +AVCodecWrapper::AVCodecWrapper(AVCodec *codec, const LibraryVersions &libraryVersions) + : codec(codec), libraryVersions(libraryVersions) +{ +} + +AVCodecID AVCodecWrapper::getCodecID() +{ + this->update(); + return this->id; +} + +std::string AVCodecWrapper::getName() +{ + this->update(); + return this->name; +} +std::string AVCodecWrapper::getLongName() +{ + this->update(); + return this->long_name; +} + void AVCodecWrapper::update() { if (codec == nullptr) return; - if (libVer.avcodec.major == 56 || libVer.avcodec.major == 57 || libVer.avcodec.major == 58) + if (libraryVersions.avcodec.major == 56 || // + libraryVersions.avcodec.major == 57 || // + libraryVersions.avcodec.major == 58) { auto p = reinterpret_cast(codec); - this->name = QString(p->name); - this->long_name = QString(p->long_name); + this->name = std::string(p->name); + this->long_name = std::string(p->long_name); this->type = p->type; this->id = p->id; this->capabilities = p->capabilities; @@ -110,11 +134,11 @@ void AVCodecWrapper::update() this->channel_layouts = convertRawListToVec(p->channel_layouts, uint64_t(0)); this->max_lowres = p->max_lowres; } - else if (libVer.avcodec.major == 59) + else if (libraryVersions.avcodec.major == 59) { auto p = reinterpret_cast(codec); - this->name = QString(p->name); - this->long_name = QString(p->long_name); + this->name = std::string(p->name); + this->long_name = std::string(p->long_name); this->type = p->type; this->id = p->id; this->capabilities = p->capabilities; diff --git a/YUViewLib/src/ffmpeg/AVCodecWrapper.h b/YUViewLib/src/ffmpeg/AVCodecWrapper.h index 9ce2bee89..96e8eb48e 100644 --- a/YUViewLib/src/ffmpeg/AVCodecWrapper.h +++ b/YUViewLib/src/ffmpeg/AVCodecWrapper.h @@ -42,31 +42,21 @@ namespace FFmpeg class AVCodecWrapper { public: - AVCodecWrapper() {} - AVCodecWrapper(AVCodec *codec, LibraryVersion libVer) : codec(codec), libVer(libVer) {} - explicit operator bool() const { return this->codec != nullptr; } - AVCodec * getAVCodec() { return this->codec; } - AVCodecID getCodecID() - { - update(); - return this->id; - } - QString getName() - { - update(); - return this->name; - } - QString getLongName() - { - update(); - return this->long_name; - } + AVCodecWrapper() = default; + AVCodecWrapper(AVCodec *codec, const LibraryVersions &libraryVersions); + + explicit operator bool() const { return this->codec != nullptr; } + AVCodec *getAVCodec() { return this->codec; } + + AVCodecID getCodecID(); + std::string getName(); + std::string getLongName(); private: void update(); - QString name{}; - QString long_name{}; + std::string name{}; + std::string long_name{}; AVMediaType type; AVCodecID id{AV_CODEC_ID_NONE}; int capabilities{0}; @@ -77,8 +67,8 @@ class AVCodecWrapper std::vector channel_layouts; uint8_t max_lowres{0}; - AVCodec * codec{nullptr}; - LibraryVersion libVer; + AVCodec * codec{nullptr}; + LibraryVersions libraryVersions; }; } // namespace FFmpeg diff --git a/YUViewLib/src/ffmpeg/AVFormatContextWrapper.cpp b/YUViewLib/src/ffmpeg/AVFormatContextWrapper.cpp index 4bcc37278..c9b9475d3 100644 --- a/YUViewLib/src/ffmpeg/AVFormatContextWrapper.cpp +++ b/YUViewLib/src/ffmpeg/AVFormatContextWrapper.cpp @@ -184,10 +184,11 @@ typedef struct AVFormatContext_59_60 } // namespace -AVFormatContextWrapper::AVFormatContextWrapper(AVFormatContext *c, LibraryVersion v) +AVFormatContextWrapper::AVFormatContextWrapper(AVFormatContext * c, + const LibraryVersions &libraryVersions) { - this->ctx = c; - this->libVer = v; + this->ctx = c; + this->libraryVersions = libraryVersions; this->update(); } @@ -252,13 +253,13 @@ void AVFormatContextWrapper::update() this->streams.clear(); // Copy values from the source pointer - if (this->libVer.avformat.major == 56) + if (this->libraryVersions.avformat.major == 56) { auto p = reinterpret_cast(this->ctx); this->ctx_flags = p->ctx_flags; this->nb_streams = p->nb_streams; for (unsigned i = 0; i < this->nb_streams; i++) - this->streams.append(AVStreamWrapper(p->streams[i], this->libVer)); + this->streams.append(AVStreamWrapper(p->streams[i], this->libraryVersions)); this->filename = QString(p->filename); this->start_time = p->start_time; this->duration = p->duration; @@ -278,15 +279,15 @@ void AVFormatContextWrapper::update() this->nb_chapters = p->nb_chapters; this->metadata = AVDictionaryWrapper(p->metadata); - this->iformat = AVInputFormatWrapper(p->iformat, libVer); + this->iformat = AVInputFormatWrapper(p->iformat, this->libraryVersions); } - else if (this->libVer.avformat.major == 57) + else if (this->libraryVersions.avformat.major == 57) { auto p = reinterpret_cast(this->ctx); this->ctx_flags = p->ctx_flags; this->nb_streams = p->nb_streams; for (unsigned i = 0; i < nb_streams; i++) - this->streams.append(AVStreamWrapper(p->streams[i], this->libVer)); + this->streams.append(AVStreamWrapper(p->streams[i], this->libraryVersions)); this->filename = QString(p->filename); this->start_time = p->start_time; this->duration = p->duration; @@ -306,15 +307,15 @@ void AVFormatContextWrapper::update() this->nb_chapters = p->nb_chapters; this->metadata = AVDictionaryWrapper(p->metadata); - this->iformat = AVInputFormatWrapper(p->iformat, libVer); + this->iformat = AVInputFormatWrapper(p->iformat, this->libraryVersions); } - else if (this->libVer.avformat.major == 58) + else if (this->libraryVersions.avformat.major == 58) { auto p = reinterpret_cast(this->ctx); this->ctx_flags = p->ctx_flags; this->nb_streams = p->nb_streams; for (unsigned i = 0; i < nb_streams; i++) - this->streams.append(AVStreamWrapper(p->streams[i], this->libVer)); + this->streams.append(AVStreamWrapper(p->streams[i], this->libraryVersions)); this->filename = QString(p->filename); this->start_time = p->start_time; this->duration = p->duration; @@ -334,15 +335,16 @@ void AVFormatContextWrapper::update() this->nb_chapters = p->nb_chapters; this->metadata = AVDictionaryWrapper(p->metadata); - this->iformat = AVInputFormatWrapper(p->iformat, this->libVer); + this->iformat = AVInputFormatWrapper(p->iformat, this->libraryVersions); } - else if (this->libVer.avformat.major == 59 || this->libVer.avformat.major == 60) + else if (this->libraryVersions.avformat.major == 59 || // + this->libraryVersions.avformat.major == 60) { auto p = reinterpret_cast(this->ctx); this->ctx_flags = p->ctx_flags; this->nb_streams = p->nb_streams; for (unsigned i = 0; i < nb_streams; i++) - this->streams.append(AVStreamWrapper(p->streams[i], this->libVer)); + this->streams.append(AVStreamWrapper(p->streams[i], this->libraryVersions)); this->filename = QString(p->url); this->start_time = p->start_time; this->duration = p->duration; @@ -362,7 +364,7 @@ void AVFormatContextWrapper::update() this->nb_chapters = p->nb_chapters; this->metadata = AVDictionaryWrapper(p->metadata); - this->iformat = AVInputFormatWrapper(p->iformat, this->libVer); + this->iformat = AVInputFormatWrapper(p->iformat, this->libraryVersions); } else throw std::runtime_error("Invalid library version"); diff --git a/YUViewLib/src/ffmpeg/AVFormatContextWrapper.h b/YUViewLib/src/ffmpeg/AVFormatContextWrapper.h index 8059c51f2..46badd931 100644 --- a/YUViewLib/src/ffmpeg/AVFormatContextWrapper.h +++ b/YUViewLib/src/ffmpeg/AVFormatContextWrapper.h @@ -46,7 +46,7 @@ class AVFormatContextWrapper { public: AVFormatContextWrapper() = default; - AVFormatContextWrapper(AVFormatContext *c, LibraryVersion v); + AVFormatContextWrapper(AVFormatContext *c, const LibraryVersions &libraryVersions); void updateFrom(AVFormatContext *c); explicit operator bool() const; @@ -91,7 +91,7 @@ class AVFormatContextWrapper AVDictionaryWrapper metadata; AVFormatContext *ctx{nullptr}; - LibraryVersion libVer{}; + LibraryVersions libraryVersions{}; }; } // namespace FFmpeg diff --git a/YUViewLib/src/ffmpeg/AVFrameSideDataWrapper.cpp b/YUViewLib/src/ffmpeg/AVFrameSideDataWrapper.cpp index 2e905b1d4..a71aaae5a 100644 --- a/YUViewLib/src/ffmpeg/AVFrameSideDataWrapper.cpp +++ b/YUViewLib/src/ffmpeg/AVFrameSideDataWrapper.cpp @@ -59,53 +59,37 @@ typedef struct AVFrameSideData_57_58 } // namespace -AVFrameSideDataWrapper::AVFrameSideDataWrapper(AVFrameSideData *sideData, LibraryVersion libVer) - : sideData(sideData), libVer(libVer) +AVFrameSideDataWrapper::AVFrameSideDataWrapper(AVFrameSideData * sideData, + const LibraryVersions &libraryVersions) + : sideData(sideData), libraryVersions(libraryVersions) { - this->update(); } -size_t AVFrameSideDataWrapper::getNumberMotionVectors() -{ - this->update(); - - if (this->type != AV_FRAME_DATA_MOTION_VECTORS) - return 0; - - return AVMotionVectorWrapper::getNumberOfMotionVectors(this->libVer, this->size); -} - -AVMotionVectorWrapper AVFrameSideDataWrapper::getMotionVector(unsigned idx) -{ - this->update(); - return AVMotionVectorWrapper(this->libVer, this->data, idx); -} - -void AVFrameSideDataWrapper::update() +std::vector AVFrameSideDataWrapper::getMotionVectors() const { if (this->sideData == nullptr) - return; + return {}; - if (this->libVer.avutil.major == 54 || // - this->libVer.avutil.major == 55 || // - this->libVer.avutil.major == 56) + if (this->libraryVersions.avutil.major == 54 || // + this->libraryVersions.avutil.major == 55 || // + this->libraryVersions.avutil.major == 56) { - auto p = reinterpret_cast(sideData); - this->type = p->type; - this->data = p->data; - if (p->size > 0) - this->size = size_t(p->size); - this->metadata = p->metadata; - this->buf = p->buf; + auto p = reinterpret_cast(sideData); + + if (p->type != AV_FRAME_DATA_MOTION_VECTORS) + return {}; + + return parseMotionData(this->libraryVersions, p->data, p->size); } - else if (this->libVer.avutil.major == 57 || this->libVer.avutil.major == 58) + else if (this->libraryVersions.avutil.major == 57 || // + this->libraryVersions.avutil.major == 58) { - auto p = reinterpret_cast(sideData); - this->type = p->type; - this->data = p->data; - this->size = p->size; - this->metadata = p->metadata; - this->buf = p->buf; + auto p = reinterpret_cast(sideData); + + if (p->type != AV_FRAME_DATA_MOTION_VECTORS) + return {}; + + return parseMotionData(this->libraryVersions, p->data, p->size); } else throw std::runtime_error("Invalid library version"); diff --git a/YUViewLib/src/ffmpeg/AVFrameSideDataWrapper.h b/YUViewLib/src/ffmpeg/AVFrameSideDataWrapper.h index a3169e9c0..a626091da 100644 --- a/YUViewLib/src/ffmpeg/AVFrameSideDataWrapper.h +++ b/YUViewLib/src/ffmpeg/AVFrameSideDataWrapper.h @@ -32,8 +32,8 @@ #pragma once -#include "AVMotionVectorWrapper.h" #include "FFMpegLibrariesTypes.h" +#include "MotionVector.h" namespace FFmpeg { @@ -42,24 +42,15 @@ class AVFrameSideDataWrapper { public: AVFrameSideDataWrapper() = default; - AVFrameSideDataWrapper(AVFrameSideData *sideData, LibraryVersion libVer); + AVFrameSideDataWrapper(AVFrameSideData *sideData, const LibraryVersions &libraryVersions); - size_t getNumberMotionVectors(); - AVMotionVectorWrapper getMotionVector(unsigned idx); + std::vector getMotionVectors() const; explicit operator bool() const { return sideData != nullptr; } private: - void update(); - - AVFrameSideDataType type{}; - uint8_t * data{nullptr}; - size_t size{}; - AVDictionary * metadata{}; - AVBufferRef * buf{}; - AVFrameSideData *sideData{}; - LibraryVersion libVer; + LibraryVersions libraryVersions{}; }; -} // namespace FFmpeg \ No newline at end of file +} // namespace FFmpeg diff --git a/YUViewLib/src/ffmpeg/AVFrameWrapper.cpp b/YUViewLib/src/ffmpeg/AVFrameWrapper.cpp index de10570c9..53da0c068 100644 --- a/YUViewLib/src/ffmpeg/AVFrameWrapper.cpp +++ b/YUViewLib/src/ffmpeg/AVFrameWrapper.cpp @@ -127,16 +127,16 @@ typedef struct AVFrame_57_58 } // namespace -AVFrameWrapper::AVFrameWrapper(LibraryVersion libVersion, AVFrame *frame) +AVFrameWrapper::AVFrameWrapper(AVFrame *frame, const LibraryVersions &libraryVersions) { - this->libVer = libVersion; - this->frame = frame; + this->frame = frame; + this->libraryVersions = libraryVersions; } void AVFrameWrapper::clear() { - this->frame = nullptr; - this->libVer = {}; + this->frame = nullptr; + this->libraryVersions = {}; } uint8_t *AVFrameWrapper::getData(int component) @@ -194,7 +194,7 @@ int AVFrameWrapper::getKeyFrame() AVDictionary *AVFrameWrapper::getMetadata() { - assert(this->libVer.avutil.major >= 57); + assert(this->libraryVersions.avutil.major >= 57); this->update(); return this->metadata; } @@ -204,10 +204,10 @@ void AVFrameWrapper::update() if (this->frame == nullptr) return; - if (this->libVer.avutil.major == 54) + if (this->libraryVersions.avutil.major == 54) { auto p = reinterpret_cast(this->frame); - for (unsigned i = 0; i < AV_NUM_DATA_POINTERS; i++) + for (auto i = 0; i < AV_NUM_DATA_POINTERS; ++i) { this->data[i] = p->data[i]; this->linesize[i] = p->linesize[i]; @@ -226,11 +226,11 @@ void AVFrameWrapper::update() this->display_picture_number = p->display_picture_number; this->quality = p->quality; } - else if (this->libVer.avutil.major == 55 || // - this->libVer.avutil.major == 56) + else if (this->libraryVersions.avutil.major == 55 || // + this->libraryVersions.avutil.major == 56) { auto p = reinterpret_cast(this->frame); - for (unsigned i = 0; i < AV_NUM_DATA_POINTERS; i++) + for (auto i = 0; i < AV_NUM_DATA_POINTERS; ++i) { this->data[i] = p->data[i]; this->linesize[i] = p->linesize[i]; @@ -249,11 +249,11 @@ void AVFrameWrapper::update() this->display_picture_number = p->display_picture_number; this->quality = p->quality; } - else if (this->libVer.avutil.major == 57 || // - this->libVer.avutil.major == 58) + else if (this->libraryVersions.avutil.major == 57 || // + this->libraryVersions.avutil.major == 58) { auto p = reinterpret_cast(this->frame); - for (unsigned i = 0; i < AV_NUM_DATA_POINTERS; i++) + for (auto i = 0; i < AV_NUM_DATA_POINTERS; ++i) { this->data[i] = p->data[i]; this->linesize[i] = p->linesize[i]; @@ -277,4 +277,4 @@ void AVFrameWrapper::update() throw std::runtime_error("Invalid library version"); } -} // namespace FFmpeg \ No newline at end of file +} // namespace FFmpeg diff --git a/YUViewLib/src/ffmpeg/AVFrameWrapper.h b/YUViewLib/src/ffmpeg/AVFrameWrapper.h index 72b3998fc..c4b05992c 100644 --- a/YUViewLib/src/ffmpeg/AVFrameWrapper.h +++ b/YUViewLib/src/ffmpeg/AVFrameWrapper.h @@ -42,8 +42,7 @@ class AVFrameWrapper { public: AVFrameWrapper() = default; - AVFrameWrapper(LibraryVersion libVersion, AVFrame *frame); - ~AVFrameWrapper() = default; + AVFrameWrapper(AVFrame *frame, const LibraryVersions &libraryVersions); void clear(); @@ -81,8 +80,8 @@ class AVFrameWrapper int quality{}; AVDictionary *metadata{}; - AVFrame * frame{}; - LibraryVersion libVer{}; + AVFrame * frame{}; + LibraryVersions libraryVersions{}; }; } // namespace FFmpeg diff --git a/YUViewLib/src/ffmpeg/AVInputFormatWrapper.cpp b/YUViewLib/src/ffmpeg/AVInputFormatWrapper.cpp index 7362e3372..16cd2d955 100644 --- a/YUViewLib/src/ffmpeg/AVInputFormatWrapper.cpp +++ b/YUViewLib/src/ffmpeg/AVInputFormatWrapper.cpp @@ -53,35 +53,31 @@ typedef struct AVInputFormat_56_57_58_59_60 } // namespace -AVInputFormatWrapper::AVInputFormatWrapper() +AVInputFormatWrapper::AVInputFormatWrapper(AVInputFormat * avInputFormat, + const LibraryVersions &libraryVersions) { - this->fmt = nullptr; -} - -AVInputFormatWrapper::AVInputFormatWrapper(AVInputFormat *f, LibraryVersion v) -{ - this->fmt = f; - this->libVer = v; + this->avInputFormat = avInputFormat; + this->libraryVersions = libraryVersions; this->update(); } void AVInputFormatWrapper::update() { - if (this->fmt == nullptr) + if (this->avInputFormat == nullptr) return; - if (this->libVer.avformat.major == 56 || // - this->libVer.avformat.major == 57 || // - this->libVer.avformat.major == 58 || // - this->libVer.avformat.major == 59 || // - this->libVer.avformat.major == 60) + if (this->libraryVersions.avformat.major == 56 || // + this->libraryVersions.avformat.major == 57 || // + this->libraryVersions.avformat.major == 58 || // + this->libraryVersions.avformat.major == 59 || // + this->libraryVersions.avformat.major == 60) { - auto p = reinterpret_cast(this->fmt); - this->name = QString(p->name); - this->long_name = QString(p->long_name); + auto p = reinterpret_cast(this->avInputFormat); + this->name = std::string(p->name); + this->long_name = std::string(p->long_name); this->flags = p->flags; - this->extensions = QString(p->extensions); - this->mime_type = QString(p->mime_type); + this->extensions = std::string(p->extensions); + this->mime_type = std::string(p->mime_type); } } diff --git a/YUViewLib/src/ffmpeg/AVInputFormatWrapper.h b/YUViewLib/src/ffmpeg/AVInputFormatWrapper.h index ec1ebdf2c..0372b2c3c 100644 --- a/YUViewLib/src/ffmpeg/AVInputFormatWrapper.h +++ b/YUViewLib/src/ffmpeg/AVInputFormatWrapper.h @@ -40,26 +40,24 @@ namespace FFmpeg class AVInputFormatWrapper { public: - AVInputFormatWrapper(); - AVInputFormatWrapper(AVInputFormat *f, LibraryVersion v); + AVInputFormatWrapper() = default; + AVInputFormatWrapper(AVInputFormat *avInputFormat, const LibraryVersions &libraryVersions); - explicit operator bool() const { return fmt != nullptr; }; + explicit operator bool() const { return this->avInputFormat != nullptr; }; private: // Update all private values from the AVCodecContext void update(); // These are here for debugging purposes. - QString name{}; - QString long_name{}; - int flags{}; - QString extensions{}; - // const struct AVCodecTag * const *codec_tag; - // const AVClass *priv_class; - QString mime_type{}; - - AVInputFormat *fmt{}; - LibraryVersion libVer{}; + std::string name{}; + std::string long_name{}; + int flags{}; + std::string extensions{}; + std::string mime_type{}; + + AVInputFormat * avInputFormat{}; + LibraryVersions libraryVersions{}; }; -} // namespace FFmpeg \ No newline at end of file +} // namespace FFmpeg diff --git a/YUViewLib/src/ffmpeg/AVPacketWrapper.cpp b/YUViewLib/src/ffmpeg/AVPacketWrapper.cpp index 1d144ca97..06c64b4df 100644 --- a/YUViewLib/src/ffmpeg/AVPacketWrapper.cpp +++ b/YUViewLib/src/ffmpeg/AVPacketWrapper.cpp @@ -129,27 +129,28 @@ bool checkForObuFormat(QByteArray &data) } // namespace -AVPacketWrapper::AVPacketWrapper(LibraryVersion libVersion, AVPacket *packet) +AVPacketWrapper::AVPacketWrapper(AVPacket *packet, const LibraryVersions &libraryVersions) { assert(packet != nullptr); - this->libVer = libVersion; + this->libraryVersions = libraryVersions; - if (this->libVer.avcodec.major == 56) + if (this->libraryVersions.avcodec.major == 56) { auto p = reinterpret_cast(packet); p->data = nullptr; p->size = 0; this->pkt = reinterpret_cast(p); } - else if (this->libVer.avcodec.major == 57 || this->libVer.avcodec.major == 58) + else if (this->libraryVersions.avcodec.major == 57 || // + this->libraryVersions.avcodec.major == 58) { auto p = reinterpret_cast(packet); p->data = nullptr; p->size = 0; this->pkt = reinterpret_cast(p); } - else if (this->libVer.avcodec.major == 59 || // - this->libVer.avcodec.major == 60) + else if (this->libraryVersions.avcodec.major == 59 || // + this->libraryVersions.avcodec.major == 60) { auto p = reinterpret_cast(packet); p->data = nullptr; @@ -162,13 +163,13 @@ AVPacketWrapper::AVPacketWrapper(LibraryVersion libVersion, AVPacket *packet) void AVPacketWrapper::clear() { - this->pkt = nullptr; - this->libVer = {}; + this->pkt = nullptr; + this->libraryVersions = {}; } void AVPacketWrapper::setData(QByteArray &set_data) { - if (this->libVer.avcodec.major == 56) + if (this->libraryVersions.avcodec.major == 56) { auto p = reinterpret_cast(this->pkt); p->data = (uint8_t *)set_data.data(); @@ -176,7 +177,8 @@ void AVPacketWrapper::setData(QByteArray &set_data) data = p->data; size = p->size; } - else if (this->libVer.avcodec.major == 57 || this->libVer.avcodec.major == 58) + else if (this->libraryVersions.avcodec.major == 57 || // + this->libraryVersions.avcodec.major == 58) { auto p = reinterpret_cast(this->pkt); p->data = (uint8_t *)set_data.data(); @@ -184,8 +186,8 @@ void AVPacketWrapper::setData(QByteArray &set_data) data = p->data; size = p->size; } - else if (this->libVer.avcodec.major == 59 || // - this->libVer.avcodec.major == 60) + else if (this->libraryVersions.avcodec.major == 59 || // + this->libraryVersions.avcodec.major == 60) { auto p = reinterpret_cast(this->pkt); p->data = (uint8_t *)set_data.data(); @@ -199,20 +201,21 @@ void AVPacketWrapper::setData(QByteArray &set_data) void AVPacketWrapper::setPTS(int64_t pts) { - if (this->libVer.avcodec.major == 56) + if (this->libraryVersions.avcodec.major == 56) { auto p = reinterpret_cast(this->pkt); p->pts = pts; this->pts = pts; } - else if (this->libVer.avcodec.major == 57 || this->libVer.avcodec.major == 58) + else if (this->libraryVersions.avcodec.major == 57 || // + this->libraryVersions.avcodec.major == 58) { auto p = reinterpret_cast(this->pkt); p->pts = pts; this->pts = pts; } - else if (this->libVer.avcodec.major == 59 || // - this->libVer.avcodec.major == 60) + else if (this->libraryVersions.avcodec.major == 59 || // + this->libraryVersions.avcodec.major == 60) { auto p = reinterpret_cast(this->pkt); p->pts = pts; @@ -224,20 +227,21 @@ void AVPacketWrapper::setPTS(int64_t pts) void AVPacketWrapper::setDTS(int64_t dts) { - if (this->libVer.avcodec.major == 56) + if (this->libraryVersions.avcodec.major == 56) { auto p = reinterpret_cast(this->pkt); p->dts = dts; this->dts = dts; } - else if (this->libVer.avcodec.major == 57 || this->libVer.avcodec.major == 58) + else if (this->libraryVersions.avcodec.major == 57 || // + this->libraryVersions.avcodec.major == 58) { auto p = reinterpret_cast(this->pkt); p->dts = dts; this->dts = dts; } - else if (this->libVer.avcodec.major == 59 || // - this->libVer.avcodec.major == 60) + else if (this->libraryVersions.avcodec.major == 59 || // + this->libraryVersions.avcodec.major == 60) { auto p = reinterpret_cast(this->pkt); p->dts = dts; @@ -358,7 +362,7 @@ void AVPacketWrapper::update() if (this->pkt == nullptr) return; - if (this->libVer.avcodec.major == 56) + if (this->libraryVersions.avcodec.major == 56) { auto p = reinterpret_cast(this->pkt); @@ -374,8 +378,8 @@ void AVPacketWrapper::update() this->duration = p->duration; this->pos = p->pos; } - else if (this->libVer.avcodec.major == 57 || // - this->libVer.avcodec.major == 58) + else if (this->libraryVersions.avcodec.major == 57 || // + this->libraryVersions.avcodec.major == 58) { auto p = reinterpret_cast(this->pkt); @@ -391,8 +395,8 @@ void AVPacketWrapper::update() this->duration = p->duration; this->pos = p->pos; } - else if (this->libVer.avcodec.major == 59 || // - this->libVer.avcodec.major == 60) + else if (this->libraryVersions.avcodec.major == 59 || // + this->libraryVersions.avcodec.major == 60) { auto p = reinterpret_cast(this->pkt); diff --git a/YUViewLib/src/ffmpeg/AVPacketWrapper.h b/YUViewLib/src/ffmpeg/AVPacketWrapper.h index 7d727c0e7..fb62b484e 100644 --- a/YUViewLib/src/ffmpeg/AVPacketWrapper.h +++ b/YUViewLib/src/ffmpeg/AVPacketWrapper.h @@ -119,7 +119,7 @@ class AVPacketWrapper { public: AVPacketWrapper() = default; - AVPacketWrapper(LibraryVersion libVersion, AVPacket *packet); + AVPacketWrapper(AVPacket *packet, const LibraryVersions &libraryVersions); void clear(); @@ -167,7 +167,7 @@ class AVPacketWrapper PacketType packetType{}; AVPacket * pkt{}; - LibraryVersion libVer{}; + LibraryVersions libraryVersions{}; PacketDataFormat packetFormat{PacketDataFormat::Unknown}; }; diff --git a/YUViewLib/src/ffmpeg/AVPixFmtDescriptorWrapper.cpp b/YUViewLib/src/ffmpeg/AVPixFmtDescriptorWrapper.cpp index 91c1c6768..28c133bff 100644 --- a/YUViewLib/src/ffmpeg/AVPixFmtDescriptorWrapper.cpp +++ b/YUViewLib/src/ffmpeg/AVPixFmtDescriptorWrapper.cpp @@ -154,13 +154,13 @@ bool flagsSupported(const AVPixFmtDescriptorWrapper::Flags &flags) } // namespace -AVPixFmtDescriptorWrapper::AVPixFmtDescriptorWrapper(AVPixFmtDescriptor *descriptor, - LibraryVersion libVer) +AVPixFmtDescriptorWrapper::AVPixFmtDescriptorWrapper(AVPixFmtDescriptor * descriptor, + const LibraryVersions &libraryVersions) { - if (libVer.avutil.major == 54) + if (libraryVersions.avutil.major == 54) { auto p = reinterpret_cast(descriptor); - this->name = QString(p->name); + this->name = std::string(p->name); this->nb_components = p->nb_components; this->log2_chroma_w = p->log2_chroma_w; this->log2_chroma_h = p->log2_chroma_h; @@ -175,12 +175,12 @@ AVPixFmtDescriptorWrapper::AVPixFmtDescriptorWrapper(AVPixFmtDescriptor *descrip this->comp[i].depth = p->comp[i].depth_minus1 + 1; } - aliases = QString(p->alias); + aliases = std::string(p->alias); } - else if (libVer.avutil.major == 55) + else if (libraryVersions.avutil.major == 55) { auto p = reinterpret_cast(descriptor); - this->name = QString(p->name); + this->name = std::string(p->name); this->nb_components = p->nb_components; this->log2_chroma_w = p->log2_chroma_w; this->log2_chroma_h = p->log2_chroma_h; @@ -195,12 +195,12 @@ AVPixFmtDescriptorWrapper::AVPixFmtDescriptorWrapper(AVPixFmtDescriptor *descrip this->comp[i].depth = p->comp[i].depth; } - aliases = QString(p->alias); + aliases = std::string(p->alias); } - else if (libVer.avutil.major == 56) + else if (libraryVersions.avutil.major == 56) { auto p = reinterpret_cast(descriptor); - this->name = QString(p->name); + this->name = std::string(p->name); this->nb_components = p->nb_components; this->log2_chroma_w = p->log2_chroma_w; this->log2_chroma_h = p->log2_chroma_h; @@ -215,13 +215,13 @@ AVPixFmtDescriptorWrapper::AVPixFmtDescriptorWrapper(AVPixFmtDescriptor *descrip this->comp[i].depth = p->comp[i].depth; } - aliases = QString(p->alias); + aliases = std::string(p->alias); } - else if (libVer.avutil.major == 57 || // - libVer.avutil.major == 58) + else if (libraryVersions.avutil.major == 57 || // + libraryVersions.avutil.major == 58) { auto p = reinterpret_cast(descriptor); - this->name = QString(p->name); + this->name = std::string(p->name); this->nb_components = p->nb_components; this->log2_chroma_w = p->log2_chroma_w; this->log2_chroma_h = p->log2_chroma_h; @@ -236,7 +236,7 @@ AVPixFmtDescriptorWrapper::AVPixFmtDescriptorWrapper(AVPixFmtDescriptor *descrip this->comp[i].depth = p->comp[i].depth; } - aliases = QString(p->alias); + aliases = std::string(p->alias); } } diff --git a/YUViewLib/src/ffmpeg/AVPixFmtDescriptorWrapper.h b/YUViewLib/src/ffmpeg/AVPixFmtDescriptorWrapper.h index d8642a3a3..ee7390326 100644 --- a/YUViewLib/src/ffmpeg/AVPixFmtDescriptorWrapper.h +++ b/YUViewLib/src/ffmpeg/AVPixFmtDescriptorWrapper.h @@ -44,7 +44,7 @@ class AVPixFmtDescriptorWrapper { public: AVPixFmtDescriptorWrapper() = default; - AVPixFmtDescriptorWrapper(AVPixFmtDescriptor *sideData, LibraryVersion libVer); + AVPixFmtDescriptorWrapper(AVPixFmtDescriptor *sideData, const LibraryVersions &libraryVersions); video::RawFormat getRawFormat() const; video::yuv::PixelFormatYUV getPixelFormatYUV() const; @@ -53,8 +53,8 @@ class AVPixFmtDescriptorWrapper bool setValuesFromPixelFormatYUV(video::yuv::PixelFormatYUV fmt); // AVPixFmtDescriptor - QString name; - int nb_components{}; ///< The number of components each pixel has, (1-4) + std::string name; + int nb_components{}; ///< The number of components each pixel has, (1-4) /** * Amount to shift the luma width/height right to find the chroma width/height. @@ -100,7 +100,7 @@ class AVPixFmtDescriptorWrapper int depth{}; ///< number of bits in the component }; - QString aliases{}; + std::string aliases{}; AVComponentDescriptor comp[4]; bool operator==(const AVPixFmtDescriptorWrapper &a); diff --git a/YUViewLib/src/ffmpeg/AVStreamWrapper.cpp b/YUViewLib/src/ffmpeg/AVStreamWrapper.cpp index b465bb76a..4436f57d5 100644 --- a/YUViewLib/src/ffmpeg/AVStreamWrapper.cpp +++ b/YUViewLib/src/ffmpeg/AVStreamWrapper.cpp @@ -231,17 +231,17 @@ typedef struct AVStream_60 } // namespace -AVStreamWrapper::AVStreamWrapper(AVStream *src_str, LibraryVersion v) +AVStreamWrapper::AVStreamWrapper(AVStream *src_str, const LibraryVersions &libraryVersions) { - this->stream = src_str; - this->libVer = v; + this->stream = src_str; + this->libraryVersions = libraryVersions; this->update(); } AVMediaType AVStreamWrapper::getCodecType() { this->update(); - if (this->libVer.avformat.major <= 56 || !this->codecpar) + if (this->libraryVersions.avformat.major <= 56 || !this->codecpar) return this->codec.getCodecType(); return this->codecpar.getCodecType(); } @@ -268,7 +268,7 @@ AVCodecID AVStreamWrapper::getCodecID() if (this->stream == nullptr) return AV_CODEC_ID_NONE; - if (this->libVer.avformat.major <= 56 || !this->codecpar) + if (this->libraryVersions.avformat.major <= 56 || !this->codecpar) return this->codec.getCodecID(); else return this->codecpar.getCodecID(); @@ -298,7 +298,7 @@ AVRational AVStreamWrapper::getTimeBase() Size AVStreamWrapper::getFrameSize() { this->update(); - if (this->libVer.avformat.major <= 56 || !this->codecpar) + if (this->libraryVersions.avformat.major <= 56 || !this->codecpar) return this->codec.getSize(); return this->codecpar.getSize(); } @@ -306,7 +306,7 @@ Size AVStreamWrapper::getFrameSize() AVColorSpace AVStreamWrapper::getColorspace() { this->update(); - if (this->libVer.avformat.major <= 56 || !this->codecpar) + if (this->libraryVersions.avformat.major <= 56 || !this->codecpar) return this->codec.getColorspace(); return this->codecpar.getColorspace(); } @@ -314,7 +314,7 @@ AVColorSpace AVStreamWrapper::getColorspace() AVPixelFormat AVStreamWrapper::getPixelFormat() { this->update(); - if (this->libVer.avformat.major <= 56 || !this->codecpar) + if (this->libraryVersions.avformat.major <= 56 || !this->codecpar) return this->codec.getPixelFormat(); return this->codecpar.getPixelFormat(); } @@ -322,7 +322,7 @@ AVPixelFormat AVStreamWrapper::getPixelFormat() QByteArray AVStreamWrapper::getExtradata() { this->update(); - if (this->libVer.avformat.major <= 56 || !this->codecpar) + if (this->libraryVersions.avformat.major <= 56 || !this->codecpar) return this->codec.getExtradata(); return this->codecpar.getExtradata(); } @@ -345,12 +345,12 @@ void AVStreamWrapper::update() return; // Copy values from the source pointer - if (libVer.avformat.major == 56) + if (this->libraryVersions.avformat.major == 56) { auto p = reinterpret_cast(this->stream); this->index = p->index; this->id = p->id; - this->codec = AVCodecContextWrapper(p->codec, libVer); + this->codec = AVCodecContextWrapper(p->codec, this->libraryVersions); this->time_base = p->time_base; this->start_time = p->start_time; this->duration = p->duration; @@ -362,12 +362,12 @@ void AVStreamWrapper::update() this->nb_side_data = p->nb_side_data; this->event_flags = p->event_flags; } - else if (libVer.avformat.major == 57) + else if (this->libraryVersions.avformat.major == 57) { auto p = reinterpret_cast(this->stream); this->index = p->index; this->id = p->id; - this->codec = AVCodecContextWrapper(p->codec, libVer); + this->codec = AVCodecContextWrapper(p->codec, this->libraryVersions); this->time_base = p->time_base; this->start_time = p->start_time; this->duration = p->duration; @@ -378,14 +378,14 @@ void AVStreamWrapper::update() this->avg_frame_rate = p->avg_frame_rate; this->nb_side_data = p->nb_side_data; this->event_flags = p->event_flags; - this->codecpar = AVCodecParametersWrapper(p->codecpar, libVer); + this->codecpar = AVCodecParametersWrapper(p->codecpar, this->libraryVersions); } - else if (libVer.avformat.major == 58) + else if (this->libraryVersions.avformat.major == 58) { auto p = reinterpret_cast(this->stream); this->index = p->index; this->id = p->id; - this->codec = AVCodecContextWrapper(p->codec, libVer); + this->codec = AVCodecContextWrapper(p->codec, this->libraryVersions); this->time_base = p->time_base; this->start_time = p->start_time; this->duration = p->duration; @@ -396,9 +396,9 @@ void AVStreamWrapper::update() this->avg_frame_rate = p->avg_frame_rate; this->nb_side_data = p->nb_side_data; this->event_flags = p->event_flags; - this->codecpar = AVCodecParametersWrapper(p->codecpar, libVer); + this->codecpar = AVCodecParametersWrapper(p->codecpar, this->libraryVersions); } - else if (libVer.avformat.major == 59) + else if (this->libraryVersions.avformat.major == 59) { auto p = reinterpret_cast(this->stream); this->index = p->index; @@ -413,9 +413,9 @@ void AVStreamWrapper::update() this->avg_frame_rate = p->avg_frame_rate; this->nb_side_data = p->nb_side_data; this->event_flags = p->event_flags; - this->codecpar = AVCodecParametersWrapper(p->codecpar, libVer); + this->codecpar = AVCodecParametersWrapper(p->codecpar, this->libraryVersions); } - else if (libVer.avformat.major == 60) + else if (this->libraryVersions.avformat.major == 60) { auto p = reinterpret_cast(this->stream); this->index = p->index; @@ -430,7 +430,7 @@ void AVStreamWrapper::update() this->avg_frame_rate = p->avg_frame_rate; this->nb_side_data = p->nb_side_data; this->event_flags = p->event_flags; - this->codecpar = AVCodecParametersWrapper(p->codecpar, libVer); + this->codecpar = AVCodecParametersWrapper(p->codecpar, this->libraryVersions); } else throw std::runtime_error("Invalid library version"); @@ -449,7 +449,7 @@ QStringPairList AVStreamWrapper::getInfoText(AVCodecIDWrapper &codecIdWrapper) info.append(QStringPair("Codec Type", getCodecTypeName())); info.append(QStringPair("Codec ID", QString::number((int)getCodecID()))); - info.append(QStringPair("Codec Name", codecIdWrapper.getCodecName())); + info.append(QStringPair("Codec Name", QString::fromStdString(codecIdWrapper.getCodecName()))); info.append( QStringPair("Time base", QString("%1/%2").arg(this->time_base.num).arg(this->time_base.den))); info.append(QStringPair("Start Time", diff --git a/YUViewLib/src/ffmpeg/AVStreamWrapper.h b/YUViewLib/src/ffmpeg/AVStreamWrapper.h index daffc288d..6912ce698 100644 --- a/YUViewLib/src/ffmpeg/AVStreamWrapper.h +++ b/YUViewLib/src/ffmpeg/AVStreamWrapper.h @@ -45,7 +45,7 @@ class AVStreamWrapper { public: AVStreamWrapper() {} - AVStreamWrapper(AVStream *src_str, LibraryVersion v); + AVStreamWrapper(AVStream *src_str, const LibraryVersions &libraryVersions); explicit operator bool() const { return this->stream != nullptr; }; QStringPairList getInfoText(AVCodecIDWrapper &codecIdWrapper); @@ -86,8 +86,8 @@ class AVStreamWrapper // The AVCodecParameters are present from avformat major version 57 and up. AVCodecParametersWrapper codecpar{}; - AVStream * stream{}; - LibraryVersion libVer{}; + AVStream * stream{}; + LibraryVersions libraryVersions{}; }; } // namespace FFmpeg \ No newline at end of file diff --git a/YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.h b/YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.h index 1cb975f23..08d312afc 100644 --- a/YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.h +++ b/YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.h @@ -35,6 +35,7 @@ #include #include #include +#include #include /* This file defines all FFmpeg specific defines like structs, enums and some common things like @@ -390,24 +391,59 @@ enum AVSampleFormat struct Version { + Version() = default; + Version(const int major) { this->major = major; } + + constexpr bool operator!=(const Version &other) const + { + if (this->major != other.major) + return true; + if (this->minor && other.minor && this->minor.value() != other.minor.value()) + return true; + if (this->micro && other.micro && this->micro.value() != other.micro.value()) + return true; + + return false; + } + + static Version fromFFmpegVersion(const unsigned ffmpegVersion) + { + Version v; + v.major = AV_VERSION_MAJOR(ffmpegVersion); + v.minor = AV_VERSION_MINOR(ffmpegVersion); + v.micro = AV_VERSION_MICRO(ffmpegVersion); + return v; + } + int major{}; std::optional minor{}; std::optional micro{}; }; -struct LibraryVersion +inline std::string to_string(const Version &version) { - LibraryVersion() = default; - LibraryVersion(int avutilMajor, int avcodecMajor, int avformatMajor, int swresampleMajor) + std::ostringstream stream; + stream << "v" << version.major; + if (version.minor) { - this->avutil.major = avutilMajor; - this->avcodec.major = avcodecMajor; - this->avformat.major = avformatMajor; - this->swresample.major = swresampleMajor; + stream << "." << version.minor.value(); + if (version.micro) + stream << "." << version.micro.value(); } - Version avutil{}; - Version avcodec{}; + return stream.str(); +} + +static std::ostream &operator<<(std::ostream &stream, const Version &version) +{ + stream << to_string(version); + return stream; +} + +struct LibraryVersions +{ Version avformat{}; + Version avcodec{}; + Version avutil{}; Version swresample{}; }; diff --git a/YUViewLib/src/ffmpeg/FFmpegLibraryFunctions.cpp b/YUViewLib/src/ffmpeg/FFmpegLibraryFunctions.cpp index 402e9c80c..8e39a5fbd 100644 --- a/YUViewLib/src/ffmpeg/FFmpegLibraryFunctions.cpp +++ b/YUViewLib/src/ffmpeg/FFmpegLibraryFunctions.cpp @@ -211,7 +211,7 @@ FFmpegLibraryFunctions::~FFmpegLibraryFunctions() LibraryLoadingResult FFmpegLibraryFunctions::loadFFmpegLibraryInPath(const std::filesystem::path &path, - const LibraryVersion & libraryVersion) + const LibraryVersions & libraryVersions) { // We will load the following libraries (in this order): // avutil, swresample, avcodec, avformat. @@ -235,8 +235,8 @@ FFmpegLibraryFunctions::loadFFmpegLibraryInPath(const std::filesystem::path &pat loadingResult.addLogLine("Unload libraries"); auto loadLibrary = [&loadingResult, &absoluteDirectoryPath]( - LibraryLoader &lib, std::string libName, int version) { - const auto libraryNames = formatPossibleLibraryNames(libName, version); + LibraryLoader &lib, std::string libName, const Version &version) { + const auto libraryNames = formatPossibleLibraryNames(libName, version.major); for (const auto &possibleLibName : libraryNames) { const auto filePath = absoluteDirectoryPath / possibleLibName; @@ -245,12 +245,13 @@ FFmpegLibraryFunctions::loadFFmpegLibraryInPath(const std::filesystem::path &pat (success ? " succeded" : " failed")); return success; } + return false; }; - if (loadLibrary(this->libAvutil, "avutil", libraryVersion.avutil.major) && - loadLibrary(this->libSwresample, "swresample", libraryVersion.swresample.major) && - loadLibrary(this->libAvcodec, "avcodec", libraryVersion.avcodec.major) && - loadLibrary(this->libAvformat, "avformat", libraryVersion.avformat.major)) + if (loadLibrary(this->libAvutil, "avutil", libraryVersions.avutil) && + loadLibrary(this->libSwresample, "swresample", libraryVersions.swresample) && + loadLibrary(this->libAvcodec, "avcodec", libraryVersions.avcodec) && + loadLibrary(this->libAvformat, "avformat", libraryVersions.avformat)) { if (bindLibraryFunctionsAndUpdateResult(this->libAvformat, this->avformat, loadingResult) && bindLibraryFunctionsAndUpdateResult(this->libAvcodec, this->avcodec, loadingResult) && @@ -277,14 +278,29 @@ void FFmpegLibraryFunctions::unloadAllLibraries() this->libAvformat.unload(); } -LibraryPaths FFmpegLibraryFunctions::getLibraryPaths() const +std::vector FFmpegLibraryFunctions::getLibrariesInfo() const { - LibraryPaths paths; - paths.avFormat = this->libAvformat.getLibraryPath(); - paths.avCodec = this->libAvcodec.getLibraryPath(); - paths.avUtil = this->libAvutil.getLibraryPath(); - paths.swResample = this->libSwresample.getLibraryPath(); - return paths; + if (!this->libAvutil || !this->libSwresample || !this->libAvcodec || !this->libAvformat) + return {}; + + std::vector infoPerLIbrary; + + auto addLibraryInfo = [&infoPerLIbrary](const char * name, + const std::filesystem::path &path, + const unsigned ffmpegVersion) { + const auto libraryVersion = Version::fromFFmpegVersion(ffmpegVersion); + const auto version = to_string(libraryVersion); + + infoPerLIbrary.push_back(LibraryInfo({name, path, version})); + }; + + addLibraryInfo("AVFormat", this->libAvformat.getLibraryPath(), this->avformat.avformat_version()); + addLibraryInfo("AVCodec", this->libAvcodec.getLibraryPath(), this->avcodec.avcodec_version()); + addLibraryInfo("AVUtil", this->libAvutil.getLibraryPath(), this->avutil.avutil_version()); + addLibraryInfo( + "SwResample", this->libSwresample.getLibraryPath(), this->swresample.swresample_version()); + + return infoPerLIbrary; } } // namespace FFmpeg diff --git a/YUViewLib/src/ffmpeg/FFmpegLibraryFunctions.h b/YUViewLib/src/ffmpeg/FFmpegLibraryFunctions.h index 7ac4e24e3..4bc05b7e3 100644 --- a/YUViewLib/src/ffmpeg/FFmpegLibraryFunctions.h +++ b/YUViewLib/src/ffmpeg/FFmpegLibraryFunctions.h @@ -40,12 +40,11 @@ namespace FFmpeg { -struct LibraryPaths +struct LibraryInfo { - std::filesystem::path avFormat; - std::filesystem::path avCodec; - std::filesystem::path avUtil; - std::filesystem::path swResample; + std::string name; + std::filesystem::path path; + std::string version; }; class FFmpegLibraryFunctions @@ -55,9 +54,9 @@ class FFmpegLibraryFunctions ~FFmpegLibraryFunctions(); LibraryLoadingResult loadFFmpegLibraryInPath(const std::filesystem::path &path, - const LibraryVersion & libraryVersion); + const LibraryVersions & libraryVersions); - LibraryPaths getLibraryPaths() const; + std::vector getLibrariesInfo() const; struct AvFormatFunctions { diff --git a/YUViewLib/src/ffmpeg/FFmpegVersionHandler.cpp b/YUViewLib/src/ffmpeg/FFmpegVersionHandler.cpp index 02ea5c38c..36df6f727 100644 --- a/YUViewLib/src/ffmpeg/FFmpegVersionHandler.cpp +++ b/YUViewLib/src/ffmpeg/FFmpegVersionHandler.cpp @@ -41,75 +41,58 @@ namespace FFmpeg namespace { -tl::expected checkVersionWithLib(FFmpegLibraryFunctions &lib, - LibraryVersion version) +LibraryVersions getLibraryVersionsFromLoadedLibraries(const FFmpegLibraryFunctions &libraries) { - if (version.avcodec.major != AV_VERSION_MAJOR(lib.avcodec.avcodec_version())) - { - auto errorMessage = "The openend avcodec returned a different major version (" + - std::to_string(AV_VERSION_MAJOR(lib.avcodec.avcodec_version())) + - ") than we are " - "looking for (" + - std::to_string(version.avcodec.major) + ")."; - return tl::unexpected(errorMessage); - } + const auto avFormatVersion = Version::fromFFmpegVersion(libraries.avformat.avformat_version()); + const auto avCodecVersion = Version::fromFFmpegVersion(libraries.avcodec.avcodec_version()); + const auto avUtilVersion = Version::fromFFmpegVersion(libraries.avutil.avutil_version()); + const auto swresampleVersion = + Version::fromFFmpegVersion(libraries.swresample.swresample_version()); - if (version.avformat.major != AV_VERSION_MAJOR(lib.avformat.avformat_version())) - { - auto errorMessage = "The openend avformat returned a different major version (" + - std::to_string(AV_VERSION_MAJOR(lib.avformat.avformat_version())) + - ") than we are " - "looking for (" + - std::to_string(version.avformat.major) + ")."; - return tl::unexpected(errorMessage); - } + return {avFormatVersion, avCodecVersion, avUtilVersion, swresampleVersion}; +} - if (version.avutil.major != AV_VERSION_MAJOR(lib.avutil.avutil_version())) - { - auto errorMessage = "The openend avformat returned a different major version (" + - std::to_string(AV_VERSION_MAJOR(lib.avutil.avutil_version())) + - ") than we are " - "looking for (" + - std::to_string(version.avutil.major) + ")."; - return tl::unexpected(errorMessage); - } +tl::expected +checkMajorVersionWithLibraries(const LibraryVersions &librariesInfo, + const LibraryVersions &expectedMajorVersion) +{ + auto createErrorString = [](std::string_view libname, + const Version & realVersion, + const Version & expectedVersion) -> std::string { + std::ostringstream stream; + stream << "The openend " << libname << " returned a different version (" << realVersion + << ") than we are looking for (" << expectedVersion << ")."; + return stream.str(); + }; - if (version.swresample.major != AV_VERSION_MAJOR(lib.swresample.swresample_version())) - { - auto errorMessage = "The openend swresample returned a different major version (" + - std::to_string(AV_VERSION_MAJOR(lib.swresample.swresample_version())) + - ") than we are " - "looking for (" + - std::to_string(version.swresample.major) + ")."; - return tl::unexpected(errorMessage); - } + if (expectedMajorVersion.avcodec != librariesInfo.avcodec) + return tl::unexpected( + createErrorString("avcodec", librariesInfo.avcodec, expectedMajorVersion.avcodec)); - return {}; -} + if (expectedMajorVersion.avformat != librariesInfo.avformat) + return tl::unexpected( + createErrorString("avformat", librariesInfo.avformat, expectedMajorVersion.avformat)); -LibraryVersion addMinorAndMicroVersion(FFmpegLibraryFunctions &lib, LibraryVersion version) -{ - version.avcodec.minor = AV_VERSION_MINOR(lib.avcodec.avcodec_version()); - version.avcodec.micro = AV_VERSION_MICRO(lib.avcodec.avcodec_version()); - version.avformat.minor = AV_VERSION_MINOR(lib.avformat.avformat_version()); - version.avformat.micro = AV_VERSION_MICRO(lib.avformat.avformat_version()); - version.avutil.minor = AV_VERSION_MINOR(lib.avutil.avutil_version()); - version.avutil.micro = AV_VERSION_MICRO(lib.avutil.avutil_version()); - version.swresample.minor = AV_VERSION_MINOR(lib.swresample.swresample_version()); - version.swresample.micro = AV_VERSION_MICRO(lib.swresample.swresample_version()); + if (expectedMajorVersion.avutil != librariesInfo.avutil) + return tl::unexpected( + createErrorString("avutil", librariesInfo.avutil, expectedMajorVersion.avutil)); + + if (expectedMajorVersion.swresample != librariesInfo.swresample) + return tl::unexpected( + createErrorString("swresample", librariesInfo.swresample, expectedMajorVersion.swresample)); - return version; + return {}; } // These FFmpeg versions are supported. The numbers indicate the major version of // the following libraries in this order: Util, codec, format, swresample // The versions are sorted from newest to oldest, so that we try to open the newest ones first. -auto SupportedLibraryVersionCombinations = { - LibraryVersion(58, 60, 60, 4), - LibraryVersion(57, 59, 59, 4), - LibraryVersion(56, 58, 58, 3), - LibraryVersion(55, 57, 57, 2), - LibraryVersion(54, 56, 56, 1), +auto SupportedMajorLibraryVersionCombinations = { + LibraryVersions({Version(58), Version(60), Version(60), Version(4)}), + LibraryVersions({Version(57), Version(59), Version(59), Version(4)}), + LibraryVersions({Version(56), Version(58), Version(58), Version(3)}), + LibraryVersions({Version(55), Version(57), Version(57), Version(2)}), + LibraryVersions({Version(54), Version(56), Version(56), Version(1)}), }; } // namespace @@ -207,26 +190,9 @@ auto SupportedLibraryVersionCombinations = { //} // -std::string FFmpegVersionHandler::getLibVersionString() const -{ - std::ostringstream stream; - - auto addVersion = [&stream](const char *name, const Version &version) { - stream << name << version.major << "." << version.minor.value_or(0) << "." - << version.micro.value_or(0); - }; - - addVersion("avUtil", libVersion.avutil); - addVersion("avFormat", libVersion.avformat); - addVersion("avCodec", libVersion.avcodec); - addVersion("swresample", libVersion.swresample); - - return stream.str(); -} - AVCodecIDWrapper FFmpegVersionHandler::getCodecIDWrapper(AVCodecID id) { - auto codecName = QString(lib.avcodec.avcodec_get_name(id)); + const auto codecName = std::string(lib.avcodec.avcodec_get_name(id)); return AVCodecIDWrapper(id, codecName); } @@ -235,11 +201,11 @@ AVCodecID FFmpegVersionHandler::getCodecIDFromWrapper(AVCodecIDWrapper &wrapper) if (wrapper.getCodecID() != AV_CODEC_ID_NONE) return wrapper.getCodecID(); - int codecID = 1; - QString codecName; + int codecID = 1; + std::string codecName; do { - auto codecName = QString(this->lib.avcodec.avcodec_get_name(AVCodecID(codecID))); + codecName = std::string(this->lib.avcodec.avcodec_get_name(AVCodecID(codecID))); if (codecName == wrapper.getCodecName()) { wrapper.setCodecID(AVCodecID(codecID)); @@ -358,7 +324,7 @@ bool FFmpegVersionHandler::openInput(AVFormatContextWrapper &fmt, QString url) return false; // The wrapper will take ownership of this pointer - fmt = AVFormatContextWrapper(f_ctx, libVersion); + fmt = AVFormatContextWrapper(f_ctx, this->libraryVersions); ret = lib.avformat.avformat_find_stream_info(fmt.getFormatCtx(), nullptr); if (ret < 0) @@ -369,7 +335,8 @@ bool FFmpegVersionHandler::openInput(AVFormatContextWrapper &fmt, QString url) AVCodecParametersWrapper FFmpegVersionHandler::allocCodecParameters() { - return AVCodecParametersWrapper(this->lib.avcodec.avcodec_parameters_alloc(), libVersion); + return AVCodecParametersWrapper(this->lib.avcodec.avcodec_parameters_alloc(), + this->libraryVersions); } AVCodecWrapper FFmpegVersionHandler::findDecoder(AVCodecIDWrapper codecId) @@ -378,13 +345,13 @@ AVCodecWrapper FFmpegVersionHandler::findDecoder(AVCodecIDWrapper codecId) AVCodec * c = this->lib.avcodec.avcodec_find_decoder(avCodecID); if (c == nullptr) return {}; - return AVCodecWrapper(c, libVersion); + return AVCodecWrapper(c, this->libraryVersions); } AVCodecContextWrapper FFmpegVersionHandler::allocDecoder(AVCodecWrapper &codec) { return AVCodecContextWrapper(this->lib.avcodec.avcodec_alloc_context3(codec.getAVCodec()), - libVersion); + this->libraryVersions); } int FFmpegVersionHandler::dictSet(AVDictionaryWrapper &dict, @@ -426,13 +393,13 @@ AVFrameSideDataWrapper FFmpegVersionHandler::getSideData(AVFrameWrapper & fra AVFrameSideDataType type) { auto sd = this->lib.avutil.av_frame_get_side_data(frame.getFrame(), type); - return AVFrameSideDataWrapper(sd, libVersion); + return AVFrameSideDataWrapper(sd, this->libraryVersions); } AVDictionaryWrapper FFmpegVersionHandler::getMetadata(AVFrameWrapper &frame) { AVDictionary *dict; - if (this->libVersion.avutil.major < 57) + if (this->libraryVersions.avutil.major < 57) dict = this->lib.avutil.av_frame_get_metadata(frame.getFrame()); else dict = frame.getMetadata(); @@ -456,23 +423,24 @@ int FFmpegVersionHandler::seekBeginning(AVFormatContextWrapper &fmt) LibraryLoadingResult FFmpegVersionHandler::loadFFmpegLibraryInPath(const std::filesystem::path path) { LibraryLoadingResult result; - for (auto version : SupportedLibraryVersionCombinations) + for (auto version : SupportedMajorLibraryVersionCombinations) { if (auto loadResult = this->lib.loadFFmpegLibraryInPath(path, version)) { result.loadingLog.append(loadResult.loadingLog); - result.addLogLine("Checking versions avutil " + std::to_string(version.avutil.major) + - ", swresample " + std::to_string(version.swresample.major) + ", avcodec " + - std::to_string(version.avcodec.major) + ", avformat " + - std::to_string(version.avformat.major)); + result.addLogLine("Checking versions avutil " + to_string(version.avutil) + ", swresample " + + to_string(version.swresample) + ", avcodec " + to_string(version.avcodec) + + ", avformat " + to_string(version.avformat)); + + const auto libraryVersions = getLibraryVersionsFromLoadedLibraries(this->lib); - const auto checkVersionResult = checkVersionWithLib(this->lib, version); + const auto checkVersionResult = checkMajorVersionWithLibraries(libraryVersions, version); if (checkVersionResult.has_value()) { - this->libVersion = addMinorAndMicroVersion(this->lib, version); + this->libraryVersions = libraryVersions; - if (this->libVersion.avformat.major < 59) + if (this->libraryVersions.avformat.major < 59) this->lib.avformat.av_register_all(); result.success = true; @@ -507,7 +475,7 @@ FFmpegVersionHandler::getAvPixFmtDescriptionFromAvPixelFormat(AVPixelFormat pixF { if (pixFmt == AV_PIX_FMT_NONE) return {}; - return AVPixFmtDescriptorWrapper(lib.avutil.av_pix_fmt_desc_get(pixFmt), libVersion); + return AVPixFmtDescriptorWrapper(lib.avutil.av_pix_fmt_desc_get(pixFmt), this->libraryVersions); } AVPixelFormat @@ -522,7 +490,7 @@ FFmpegVersionHandler::getAVPixelFormatFromPixelFormatYUV(video::yuv::PixelFormat auto desc = this->lib.avutil.av_pix_fmt_desc_next(nullptr); while (desc != nullptr) { - AVPixFmtDescriptorWrapper descWrapper(desc, libVersion); + AVPixFmtDescriptorWrapper descWrapper(desc, this->libraryVersions); if (descWrapper == wrapper) return this->lib.avutil.av_pix_fmt_desc_get_id(desc); @@ -537,7 +505,7 @@ FFmpegVersionHandler::getAVPixelFormatFromPixelFormatYUV(video::yuv::PixelFormat AVFrameWrapper FFmpegVersionHandler::allocateFrame() { auto framePtr = this->lib.avutil.av_frame_alloc(); - return AVFrameWrapper(this->libVersion, framePtr); + return AVFrameWrapper(framePtr, this->libraryVersions); } void FFmpegVersionHandler::freeFrame(AVFrameWrapper &frame) @@ -551,7 +519,7 @@ AVPacketWrapper FFmpegVersionHandler::allocatePacket() { auto rawPacket = this->lib.avcodec.av_packet_alloc(); this->lib.avcodec.av_init_packet(rawPacket); - return AVPacketWrapper(this->libVersion, rawPacket); + return AVPacketWrapper(rawPacket, this->libraryVersions); } void FFmpegVersionHandler::unrefPacket(AVPacketWrapper &packet) diff --git a/YUViewLib/src/ffmpeg/FFmpegVersionHandler.h b/YUViewLib/src/ffmpeg/FFmpegVersionHandler.h index 261cb19ca..754e1ef26 100644 --- a/YUViewLib/src/ffmpeg/FFmpegVersionHandler.h +++ b/YUViewLib/src/ffmpeg/FFmpegVersionHandler.h @@ -58,8 +58,7 @@ class FFmpegVersionHandler // Try to load the ffmpeg libraries and get all the function pointers. LibraryLoadingResult loadFFmpegLibraries(std::vector searchPaths); - LibraryPaths getLibraryPaths() const { return this->lib.getLibraryPaths(); } - QString getLibVersionString() const; + std::vector getLibrariesInfo() const { return this->lib.getLibrariesInfo(); } // Only these functions can be used to get valid versions of these wrappers (they have to use // ffmpeg functions to retrieve the needed information) @@ -83,7 +82,7 @@ class FFmpegVersionHandler void flush_buffers(AVCodecContextWrapper &decCtx); - LibraryVersion libVersion; + LibraryVersions libVersions; // Open the input file. This will call avformat_open_input and avformat_find_stream_info. bool openInput(AVFormatContextWrapper &fmt, QString url); @@ -123,7 +122,8 @@ class FFmpegVersionHandler private: LibraryLoadingResult loadFFmpegLibraryInPath(const std::filesystem::path); - bool librariesLoaded{}; + bool librariesLoaded{}; + LibraryVersions libraryVersions{}; // FFmpeg has a callback where it loggs stuff. This log goes here. static QStringList logListFFmpeg; diff --git a/YUViewLib/src/ffmpeg/LibraryLoader.h b/YUViewLib/src/ffmpeg/LibraryLoader.h index 2e3a719a5..9cab5c5e2 100644 --- a/YUViewLib/src/ffmpeg/LibraryLoader.h +++ b/YUViewLib/src/ffmpeg/LibraryLoader.h @@ -49,6 +49,8 @@ class LibraryLoader auto getLibraryPath() const { return this->libraryPath; } + operator bool() const { return this->library.isLoaded(); } + private: QLibrary library; diff --git a/YUViewLib/src/ffmpeg/AVMotionVectorWrapper.cpp b/YUViewLib/src/ffmpeg/MotionVector.cpp similarity index 50% rename from YUViewLib/src/ffmpeg/AVMotionVectorWrapper.cpp rename to YUViewLib/src/ffmpeg/MotionVector.cpp index 32c027616..ca6b54054 100644 --- a/YUViewLib/src/ffmpeg/AVMotionVectorWrapper.cpp +++ b/YUViewLib/src/ffmpeg/MotionVector.cpp @@ -30,7 +30,7 @@ * along with this program. If not, see . */ -#include "AVMotionVectorWrapper.h" +#include "MotionVector.h" #include namespace FFmpeg @@ -61,52 +61,62 @@ typedef struct AVMotionVector_55_56_57 } // namespace -AVMotionVectorWrapper::AVMotionVectorWrapper(LibraryVersion &libVer, uint8_t *data, unsigned idx) +std::vector +parseMotionData(const LibraryVersions &libraryVersions, const uint8_t *data, const size_t dataSize) { - if (libVer.avutil.major == 54) + std::vector motionVectors; + if (libraryVersions.avutil.major == 54) { - auto p = reinterpret_cast(data) + idx; - this->source = p->source; - this->w = p->w; - this->h = p->h; - this->src_x = p->src_x; - this->src_y = p->src_y; - this->dst_x = p->dst_x; - this->dst_y = p->dst_y; - this->flags = p->flags; - this->motion_x = -1; - this->motion_y = -1; - this->motion_scale = -1; + const auto nrMotionVectors = dataSize / sizeof(AVMotionVector_54); + for (int index = 0; index < nrMotionVectors; ++index) + { + const auto byteOffset = sizeof(AVMotionVector_54) * index; + const auto p = reinterpret_cast(data + byteOffset); + + MotionVector motionVector; + motionVector.source = p->source; + motionVector.w = p->w; + motionVector.h = p->h; + motionVector.src_x = p->src_x; + motionVector.src_y = p->src_y; + motionVector.dst_x = p->dst_x; + motionVector.dst_y = p->dst_y; + motionVector.flags = p->flags; + motionVector.motion_x = -1; + motionVector.motion_y = -1; + motionVector.motion_scale = -1; + motionVectors.push_back(motionVector); + } + return motionVectors; } - else if (libVer.avutil.major == 55 || // - libVer.avutil.major == 56 || // - libVer.avutil.major == 57) + else if (libraryVersions.avutil.major == 55 || // + libraryVersions.avutil.major == 56 || // + libraryVersions.avutil.major == 57) { - auto p = reinterpret_cast(data) + idx; - this->source = p->source; - this->w = p->w; - this->h = p->h; - this->src_x = p->src_x; - this->src_y = p->src_y; - this->dst_x = p->dst_x; - this->dst_y = p->dst_y; - this->flags = p->flags; - this->motion_x = p->motion_x; - this->motion_y = p->motion_y; - this->motion_scale = p->motion_scale; + const auto nrMotionVectors = dataSize / sizeof(AVMotionVector_55_56_57); + for (int index = 0; index < nrMotionVectors; ++index) + { + const auto byteOffset = sizeof(AVMotionVector_55_56_57) * index; + const auto p = reinterpret_cast(data + byteOffset); + + MotionVector motionVector; + motionVector.source = p->source; + motionVector.w = p->w; + motionVector.h = p->h; + motionVector.src_x = p->src_x; + motionVector.src_y = p->src_y; + motionVector.dst_x = p->dst_x; + motionVector.dst_y = p->dst_y; + motionVector.flags = p->flags; + motionVector.motion_x = p->motion_x; + motionVector.motion_y = p->motion_y; + motionVector.motion_scale = p->motion_scale; + motionVectors.push_back(motionVector); + } + return motionVectors; } else throw std::runtime_error("Invalid library version"); } -size_t AVMotionVectorWrapper::getNumberOfMotionVectors(LibraryVersion &libVer, size_t dataSize) -{ - if (libVer.avutil.major == 54) - return dataSize / sizeof(AVMotionVector_54); - else if (libVer.avutil.major == 55 || libVer.avutil.major == 56 || libVer.avutil.major == 57) - return dataSize / sizeof(AVMotionVector_55_56_57); - else - return 0; -} - } // namespace FFmpeg diff --git a/YUViewLib/src/ffmpeg/AVMotionVectorWrapper.h b/YUViewLib/src/ffmpeg/MotionVector.h similarity index 85% rename from YUViewLib/src/ffmpeg/AVMotionVectorWrapper.h rename to YUViewLib/src/ffmpeg/MotionVector.h index 553a733d6..7941b2420 100644 --- a/YUViewLib/src/ffmpeg/AVMotionVectorWrapper.h +++ b/YUViewLib/src/ffmpeg/MotionVector.h @@ -37,16 +37,8 @@ namespace FFmpeg { -class AVMotionVectorWrapper +struct MotionVector { -public: - AVMotionVectorWrapper() = delete; - AVMotionVectorWrapper(LibraryVersion &libVer, uint8_t *data, unsigned idx); - - static size_t getNumberOfMotionVectors(LibraryVersion &libVer, size_t dataSize); - - // For performance reasons, these are public here. Since update is called at construction, these - // should be valid. int32_t source{}; uint8_t w{}; uint8_t h{}; @@ -61,4 +53,7 @@ class AVMotionVectorWrapper uint16_t motion_scale{}; }; +std::vector +parseMotionData(const LibraryVersions &libraryVersions, const uint8_t *data, const size_t dataSize); + } // namespace FFmpeg diff --git a/YUViewLib/src/filesource/FileSourceFFmpegFile.cpp b/YUViewLib/src/filesource/FileSourceFFmpegFile.cpp index 041f7b677..5f93c42f2 100644 --- a/YUViewLib/src/filesource/FileSourceFFmpegFile.cpp +++ b/YUViewLib/src/filesource/FileSourceFFmpegFile.cpp @@ -697,7 +697,7 @@ StringVec FileSourceFFmpegFile::getShortStreamDescriptionAllStreams() description << stream.getCodecTypeName().toStdString(); auto codecID = this->ff.getCodecIDWrapper(stream.getCodecID()); - description << " " << codecID.getCodecName().toStdString() << " "; + description << " " << codecID.getCodecName() << " "; description << std::pair{stream.getFrameSize().width, stream.getFrameSize().height}; diff --git a/YUViewLib/src/filesource/FileSourceFFmpegFile.h b/YUViewLib/src/filesource/FileSourceFFmpegFile.h index 3b1f64ecb..2c41be090 100644 --- a/YUViewLib/src/filesource/FileSourceFFmpegFile.h +++ b/YUViewLib/src/filesource/FileSourceFFmpegFile.h @@ -62,8 +62,7 @@ class FileSourceFFmpegFile : public QObject // TODO: How do we do this? bool atEnd() const { return endOfFile; } - // Return the name, filename and full path of every library loaded - FFmpeg::LibraryPaths getLibraryPaths() const { return this->ff.getLibraryPaths(); } + std::vector getLibrariesInfo() const { return this->ff.getLibrariesInfo(); } // Get properties of the bitstream double getFramerate() const { return frameRate; } diff --git a/YUViewLib/src/parser/AVFormat/ParserAVFormat.cpp b/YUViewLib/src/parser/AVFormat/ParserAVFormat.cpp index ae28d99b4..4cb464025 100644 --- a/YUViewLib/src/parser/AVFormat/ParserAVFormat.cpp +++ b/YUViewLib/src/parser/AVFormat/ParserAVFormat.cpp @@ -586,7 +586,8 @@ bool ParserAVFormat::runParsingOfFile(QString compressedFilePath) this->obuParser.reset(new ParserAV1OBU()); else if (this->codecID.isNone()) { - emit backgroundParsingDone("Unknown codec ID " + this->codecID.getCodecName()); + emit backgroundParsingDone("Unknown codec ID " + + QString::fromStdString(this->codecID.getCodecName())); return false; } diff --git a/YUViewLib/src/playlistitem/playlistItemCompressedVideo.cpp b/YUViewLib/src/playlistitem/playlistItemCompressedVideo.cpp index 33cd42d26..a5644ded7 100644 --- a/YUViewLib/src/playlistitem/playlistItemCompressedVideo.cpp +++ b/YUViewLib/src/playlistitem/playlistItemCompressedVideo.cpp @@ -469,8 +469,9 @@ InfoData playlistItemCompressedVideo::getInfo() const InfoItem("Reader", QString::fromStdString(InputFormatMapper.getName(this->inputFormat)))); if (this->inputFileFFmpegLoading) { - const auto libraryPaths = this->inputFileFFmpegLoading->getLibraryPaths(); - for (const auto &item : InfoItem::fromFFmpegLibraryPaths(libraryPaths)) + const auto infoItems = + InfoItem::fromFFmpegLibrariesInfo(this->inputFileFFmpegLoading->getLibrariesInfo()); + for (const auto &item : infoItems) info.items.append(item); } if (!this->unresolvableError) From 22fb303809bb30636e6a31e77fc4acae79b5bfe6 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 28 Sep 2023 22:28:34 +0200 Subject: [PATCH 4/7] Fix compilation ubuntu and fix warnings --- .../src/ffmpeg/AVCodecParametersWrapper.cpp | 6 ++-- YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.cpp | 28 ++++++++++++++++++ YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.h | 29 ++----------------- YUViewLib/src/ffmpeg/LibraryLoader.cpp | 2 +- YUViewLib/src/ffmpeg/LibraryLoader.h | 8 +++-- YUViewLib/src/ffmpeg/MotionVector.cpp | 4 +-- .../src/parser/AVFormat/ParserAVFormat.cpp | 10 ++++--- 7 files changed, 48 insertions(+), 39 deletions(-) diff --git a/YUViewLib/src/ffmpeg/AVCodecParametersWrapper.cpp b/YUViewLib/src/ffmpeg/AVCodecParametersWrapper.cpp index b38dc0e45..2b2e2870f 100644 --- a/YUViewLib/src/ffmpeg/AVCodecParametersWrapper.cpp +++ b/YUViewLib/src/ffmpeg/AVCodecParametersWrapper.cpp @@ -45,7 +45,7 @@ typedef struct AVCodecParameters_57_58_59_60 AVMediaType codec_type; AVCodecID codec_id; uint32_t codec_tag; - uint8_t * extradata; + uint8_t *extradata; int extradata_size; int format; int64_t bit_rate; @@ -69,8 +69,8 @@ typedef struct AVCodecParameters_57_58_59_60 } // namespace -AVCodecParametersWrapper::AVCodecParametersWrapper(AVCodecParameters * p, - const LibraryVersions &libraryVersionsv) +AVCodecParametersWrapper::AVCodecParametersWrapper(AVCodecParameters *p, + const LibraryVersions &libraryVersions) { this->param = p; this->libraryVersions = libraryVersions; diff --git a/YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.cpp b/YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.cpp index b6d46af7b..35db05f10 100644 --- a/YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.cpp +++ b/YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.cpp @@ -53,4 +53,32 @@ QString timestampToString(int64_t timestamp, AVRational timebase) .arg(milliseconds, 3, 10, QChar('0')); } +Version Version::fromFFmpegVersion(const unsigned ffmpegVersion) +{ + Version v; + v.major = AV_VERSION_MAJOR(ffmpegVersion); + v.minor = AV_VERSION_MINOR(ffmpegVersion); + v.micro = AV_VERSION_MICRO(ffmpegVersion); + return v; +} + +std::string to_string(const Version &version) +{ + std::ostringstream stream; + stream << "v" << version.major; + if (version.minor) + { + stream << "." << version.minor.value(); + if (version.micro) + stream << "." << version.micro.value(); + } + return stream.str(); +} + +std::ostream &operator<<(std::ostream &stream, const Version &version) +{ + stream << to_string(version); + return stream; +} + } // namespace FFmpeg diff --git a/YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.h b/YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.h index 08d312afc..2ca510866 100644 --- a/YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.h +++ b/YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.h @@ -406,38 +406,15 @@ struct Version return false; } - static Version fromFFmpegVersion(const unsigned ffmpegVersion) - { - Version v; - v.major = AV_VERSION_MAJOR(ffmpegVersion); - v.minor = AV_VERSION_MINOR(ffmpegVersion); - v.micro = AV_VERSION_MICRO(ffmpegVersion); - return v; - } + static Version fromFFmpegVersion(const unsigned ffmpegVersion); int major{}; std::optional minor{}; std::optional micro{}; }; -inline std::string to_string(const Version &version) -{ - std::ostringstream stream; - stream << "v" << version.major; - if (version.minor) - { - stream << "." << version.minor.value(); - if (version.micro) - stream << "." << version.micro.value(); - } - return stream.str(); -} - -static std::ostream &operator<<(std::ostream &stream, const Version &version) -{ - stream << to_string(version); - return stream; -} +std::string to_string(const Version &version); +std::ostream &operator<<(std::ostream &stream, const Version &version); struct LibraryVersions { diff --git a/YUViewLib/src/ffmpeg/LibraryLoader.cpp b/YUViewLib/src/ffmpeg/LibraryLoader.cpp index 5b36ad334..be0496cda 100644 --- a/YUViewLib/src/ffmpeg/LibraryLoader.cpp +++ b/YUViewLib/src/ffmpeg/LibraryLoader.cpp @@ -51,7 +51,7 @@ bool LibraryLoader::load(std::filesystem::path pathToLib) return success; }; -void *LibraryLoader::resolve(std::string functionName) +FunctionPointer LibraryLoader::resolve(std::string functionName) { auto functionPointer = this->library.resolve(functionName.c_str()); return functionPointer; diff --git a/YUViewLib/src/ffmpeg/LibraryLoader.h b/YUViewLib/src/ffmpeg/LibraryLoader.h index 9cab5c5e2..8e60318ff 100644 --- a/YUViewLib/src/ffmpeg/LibraryLoader.h +++ b/YUViewLib/src/ffmpeg/LibraryLoader.h @@ -35,6 +35,8 @@ #include #include +typedef void (*FunctionPointer)(); + namespace FFmpeg { @@ -43,9 +45,9 @@ class LibraryLoader public: LibraryLoader(/* args */) = default; - void unload(); - bool load(std::filesystem::path pathToLib); - void *resolve(std::string functionName); + void unload(); + bool load(std::filesystem::path pathToLib); + FunctionPointer resolve(std::string functionName); auto getLibraryPath() const { return this->libraryPath; } diff --git a/YUViewLib/src/ffmpeg/MotionVector.cpp b/YUViewLib/src/ffmpeg/MotionVector.cpp index ca6b54054..8130a4656 100644 --- a/YUViewLib/src/ffmpeg/MotionVector.cpp +++ b/YUViewLib/src/ffmpeg/MotionVector.cpp @@ -68,7 +68,7 @@ parseMotionData(const LibraryVersions &libraryVersions, const uint8_t *data, con if (libraryVersions.avutil.major == 54) { const auto nrMotionVectors = dataSize / sizeof(AVMotionVector_54); - for (int index = 0; index < nrMotionVectors; ++index) + for (size_t index = 0; index < nrMotionVectors; ++index) { const auto byteOffset = sizeof(AVMotionVector_54) * index; const auto p = reinterpret_cast(data + byteOffset); @@ -94,7 +94,7 @@ parseMotionData(const LibraryVersions &libraryVersions, const uint8_t *data, con libraryVersions.avutil.major == 57) { const auto nrMotionVectors = dataSize / sizeof(AVMotionVector_55_56_57); - for (int index = 0; index < nrMotionVectors; ++index) + for (size_t index = 0; index < nrMotionVectors; ++index) { const auto byteOffset = sizeof(AVMotionVector_55_56_57) * index; const auto p = reinterpret_cast(data + byteOffset); diff --git a/YUViewLib/src/parser/AVFormat/ParserAVFormat.cpp b/YUViewLib/src/parser/AVFormat/ParserAVFormat.cpp index 4cb464025..e3c88ab2c 100644 --- a/YUViewLib/src/parser/AVFormat/ParserAVFormat.cpp +++ b/YUViewLib/src/parser/AVFormat/ParserAVFormat.cpp @@ -93,7 +93,7 @@ vector ParserAVFormat::getStreamInfo() std::string ParserAVFormat::getShortStreamDescription(const int streamIndex) const { - if (streamIndex >= this->shortStreamInfoAllStreams.size()) + if (streamIndex < 0 || streamIndex >= static_cast(this->shortStreamInfoAllStreams.size())) return {}; return this->shortStreamInfoAllStreams.at(streamIndex); } @@ -245,7 +245,7 @@ bool ParserAVFormat::parseExtradata_mpeg2(ByteVector &extradata) } std::map -ParserAVFormat::parseByteVectorAnnexBStartCodes(ByteVector & data, +ParserAVFormat::parseByteVectorAnnexBStartCodes(ByteVector &data, PacketDataFormat dataFormat, BitratePlotModel::BitrateEntry packetBitrateEntry, std::shared_ptr item) @@ -256,7 +256,8 @@ ParserAVFormat::parseByteVectorAnnexBStartCodes(ByteVector & d return {}; } - auto getNextNalStart = [&data, &dataFormat](ByteVector::iterator searchStart) { + auto getNextNalStart = [&data, &dataFormat](ByteVector::iterator searchStart) + { if (dataFormat == PacketDataFormat::RawNAL) { if (std::distance(searchStart, data.end()) <= 3) @@ -343,7 +344,8 @@ bool ParserAVFormat::parseAVPacket(unsigned packetID, auto timeBase = timeBaseAllStreams[packet.getStreamIndex()]; - auto formatTimestamp = [](int64_t timestamp, AVRational timebase) -> std::string { + auto formatTimestamp = [](int64_t timestamp, AVRational timebase) -> std::string + { std::ostringstream ss; ss << timestamp << " ("; if (timestamp < 0) From d146bb21a3ef23472f822dcd65d6feaeee82fe9c Mon Sep 17 00:00:00 2001 From: Christian Feldmann Date: Tue, 3 Oct 2023 21:14:49 +0200 Subject: [PATCH 5/7] Big refactor towards a libFFmpeg++ --- .../externalLibs/LibFFmpeg++/Decoder.cpp | 43 + YUViewLib/externalLibs/LibFFmpeg++/Decoder.h | 49 + .../externalLibs/LibFFmpeg++/Demuxer.cpp | 43 + YUViewLib/externalLibs/LibFFmpeg++/Demuxer.h | 49 + .../externalLibs/LibFFmpeg++/LibFFmpeg.h | 44 + .../LibFFmpeg++/common/Expected.h | 2444 +++++++++++++++++ .../common}/FFMpegLibrariesTypes.cpp | 4 +- .../common}/FFMpegLibrariesTypes.h | 8 +- .../LibFFmpeg++/common}/MotionVector.cpp | 4 +- .../LibFFmpeg++/common}/MotionVector.h | 4 +- .../externalLibs/LibFFmpeg++/libFFmpeg++.pro | 9 + .../libHandling/FFmpegLibrariesInterface.cpp | 293 ++ .../libHandling/FFmpegLibrariesInterface.h | 92 + .../FFmpegLibrariesInterfaceBuilder.cpp | 93 + .../FFmpegLibrariesInterfaceBuilder.h | 68 + .../libHandling/FFmpegVersionHandler.cpp | 426 +++ .../libHandling/FFmpegVersionHandler.h | 132 + .../libHandling/SharedLibraryLoader.cpp} | 12 +- .../libHandling/SharedLibraryLoader.h} | 16 +- .../libraryFunctions/AVFormatFunctions.cpp | 97 + .../libraryFunctions/AVFormatFunctions.h | 59 + .../libraryFunctions/AvCodecFunctions.cpp | 127 + .../libraryFunctions/AvCodecFunctions.h | 71 + .../libraryFunctions/AvUtilFunctions.cpp | 110 + .../libraryFunctions/AvUtilFunctions.h | 65 + .../libraryFunctions/Functions.cpp | 62 + .../libHandling/libraryFunctions/Functions.h | 69 + .../libraryFunctions/SwResampleFunctions.cpp | 69 + .../libraryFunctions/SwResampleFunctions.h | 50 + .../wrappers}/AVCodecContextWrapper.cpp | 4 +- .../wrappers}/AVCodecContextWrapper.h | 7 +- .../LibFFmpeg++/wrappers}/AVCodecIDWrapper.h | 6 +- .../wrappers}/AVCodecParametersWrapper.cpp | 8 +- .../wrappers}/AVCodecParametersWrapper.h | 7 +- .../LibFFmpeg++/wrappers}/AVCodecWrapper.cpp | 4 +- .../LibFFmpeg++/wrappers}/AVCodecWrapper.h | 6 +- .../wrappers}/AVDictionaryWrapper.h | 6 +- .../wrappers}/AVFormatContextWrapper.cpp | 4 +- .../wrappers}/AVFormatContextWrapper.h | 8 +- .../wrappers}/AVFrameSideDataWrapper.cpp | 4 +- .../wrappers}/AVFrameSideDataWrapper.h | 8 +- .../LibFFmpeg++/wrappers}/AVFrameWrapper.cpp | 4 +- .../LibFFmpeg++/wrappers}/AVFrameWrapper.h | 7 +- .../wrappers}/AVInputFormatWrapper.cpp | 4 +- .../wrappers}/AVInputFormatWrapper.h | 6 +- .../LibFFmpeg++/wrappers}/AVPacketWrapper.cpp | 4 +- .../LibFFmpeg++/wrappers}/AVPacketWrapper.h | 6 +- .../wrappers}/AVPixFmtDescriptorWrapper.cpp | 4 +- .../wrappers}/AVPixFmtDescriptorWrapper.h | 6 +- .../LibFFmpeg++/wrappers}/AVStreamWrapper.cpp | 4 +- .../LibFFmpeg++/wrappers}/AVStreamWrapper.h | 8 +- YUViewLib/src/common/FileInfo.h | 3 - YUViewLib/src/common/Functions.cpp | 35 +- YUViewLib/src/common/Functions.h | 3 + YUViewLib/src/decoder/decoderFFmpeg.cpp | 10 +- YUViewLib/src/decoder/decoderFFmpeg.h | 36 +- .../src/ffmpeg/FFmpegLibraryFunctions.cpp | 306 --- YUViewLib/src/ffmpeg/FFmpegLibraryFunctions.h | 144 - YUViewLib/src/ffmpeg/FFmpegVersionHandler.cpp | 635 ----- YUViewLib/src/ffmpeg/FFmpegVersionHandler.h | 140 - .../FileInfo.cpp => ffmpeg/Functions.cpp} | 10 +- YUViewLib/src/ffmpeg/Functions.h | 45 + .../src/filesource/FileSourceFFmpegFile.cpp | 2 +- .../src/filesource/FileSourceFFmpegFile.h | 47 +- .../src/parser/AVFormat/ParserAVFormat.cpp | 2 +- .../src/parser/AVFormat/ParserAVFormat.h | 13 +- .../playlistItemCompressedVideo.h | 4 +- YUViewLib/src/ui/SettingsDialog.cpp | 2 +- 68 files changed, 4801 insertions(+), 1373 deletions(-) create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/Decoder.cpp create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/Decoder.h create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/Demuxer.cpp create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/Demuxer.h create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/LibFFmpeg.h create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/common/Expected.h rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/common}/FFMpegLibrariesTypes.cpp (98%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/common}/FFMpegLibrariesTypes.h (99%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/common}/MotionVector.cpp (98%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/common}/MotionVector.h (97%) create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/libFFmpeg++.pro create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegLibrariesInterface.cpp create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegLibrariesInterface.h create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegLibrariesInterfaceBuilder.cpp create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegLibrariesInterfaceBuilder.h create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegVersionHandler.cpp create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegVersionHandler.h rename YUViewLib/{src/ffmpeg/LibraryLoader.cpp => externalLibs/LibFFmpeg++/libHandling/SharedLibraryLoader.cpp} (89%) rename YUViewLib/{src/ffmpeg/LibraryLoader.h => externalLibs/LibFFmpeg++/libHandling/SharedLibraryLoader.h} (85%) create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AVFormatFunctions.cpp create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AVFormatFunctions.h create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AvCodecFunctions.cpp create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AvCodecFunctions.h create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AvUtilFunctions.cpp create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AvUtilFunctions.h create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/Functions.cpp create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/Functions.h create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/SwResampleFunctions.cpp create mode 100644 YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/SwResampleFunctions.h rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVCodecContextWrapper.cpp (99%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVCodecContextWrapper.h (98%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVCodecIDWrapper.h (96%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVCodecParametersWrapper.cpp (99%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVCodecParametersWrapper.h (97%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVCodecWrapper.cpp (99%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVCodecWrapper.h (96%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVDictionaryWrapper.h (95%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVFormatContextWrapper.cpp (99%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVFormatContextWrapper.h (97%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVFrameSideDataWrapper.cpp (98%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVFrameSideDataWrapper.h (94%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVFrameWrapper.cpp (99%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVFrameWrapper.h (96%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVInputFormatWrapper.cpp (98%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVInputFormatWrapper.h (96%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVPacketWrapper.cpp (99%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVPacketWrapper.h (98%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVPixFmtDescriptorWrapper.cpp (99%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVPixFmtDescriptorWrapper.h (97%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVStreamWrapper.cpp (99%) rename YUViewLib/{src/ffmpeg => externalLibs/LibFFmpeg++/wrappers}/AVStreamWrapper.h (97%) delete mode 100644 YUViewLib/src/ffmpeg/FFmpegLibraryFunctions.cpp delete mode 100644 YUViewLib/src/ffmpeg/FFmpegLibraryFunctions.h delete mode 100644 YUViewLib/src/ffmpeg/FFmpegVersionHandler.cpp delete mode 100644 YUViewLib/src/ffmpeg/FFmpegVersionHandler.h rename YUViewLib/src/{common/FileInfo.cpp => ffmpeg/Functions.cpp} (92%) create mode 100644 YUViewLib/src/ffmpeg/Functions.h diff --git a/YUViewLib/externalLibs/LibFFmpeg++/Decoder.cpp b/YUViewLib/externalLibs/LibFFmpeg++/Decoder.cpp new file mode 100644 index 000000000..c7c413688 --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/Decoder.cpp @@ -0,0 +1,43 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "Decoder.h" + +namespace LibFFmpeg +{ + +Decoder::Decoder(std::shared_ptr libraries) +{ + this->libraries = libraries; +} + +} // namespace LibFFmpeg \ No newline at end of file diff --git a/YUViewLib/externalLibs/LibFFmpeg++/Decoder.h b/YUViewLib/externalLibs/LibFFmpeg++/Decoder.h new file mode 100644 index 000000000..bd3e16f72 --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/Decoder.h @@ -0,0 +1,49 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +namespace LibFFmpeg +{ + +class Decoder +{ +public: + Decoder(std::shared_ptr libraries); + +private: + std::shared_ptr libraries; +}; + +} // namespace LibFFmpeg diff --git a/YUViewLib/externalLibs/LibFFmpeg++/Demuxer.cpp b/YUViewLib/externalLibs/LibFFmpeg++/Demuxer.cpp new file mode 100644 index 000000000..ed9fbf158 --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/Demuxer.cpp @@ -0,0 +1,43 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "Demuxer.h" + +namespace LibFFmpeg +{ + +Demuxer::Demuxer(std::shared_ptr libraries) +{ + this->libraries = libraries; +} + +} // namespace LibFFmpeg diff --git a/YUViewLib/externalLibs/LibFFmpeg++/Demuxer.h b/YUViewLib/externalLibs/LibFFmpeg++/Demuxer.h new file mode 100644 index 000000000..eb0f62e3f --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/Demuxer.h @@ -0,0 +1,49 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +namespace LibFFmpeg +{ + +class Demuxer +{ +public: + Demuxer(std::shared_ptr libraries); + +private: + std::shared_ptr libraries; +}; + +} // namespace LibFFmpeg diff --git a/YUViewLib/externalLibs/LibFFmpeg++/LibFFmpeg.h b/YUViewLib/externalLibs/LibFFmpeg++/LibFFmpeg.h new file mode 100644 index 000000000..c204321c8 --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/LibFFmpeg.h @@ -0,0 +1,44 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +namespace LibFFmpeg +{ + +// Demuxer openFileForParsing(); + +// Decoder createPacketDecoder(); + +// Check if a path contains usable ffmpeg libraries + +} // namespace LibFFmpeg diff --git a/YUViewLib/externalLibs/LibFFmpeg++/common/Expected.h b/YUViewLib/externalLibs/LibFFmpeg++/common/Expected.h new file mode 100644 index 000000000..afee404d4 --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/common/Expected.h @@ -0,0 +1,2444 @@ +/// +// expected - An implementation of std::expected with extensions +// Written in 2017 by Sy Brand (tartanllama@gmail.com, @TartanLlama) +// +// Documentation available at http://tl.tartanllama.xyz/ +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication +// along with this software. If not, see +// . +/// + +#ifndef TL_EXPECTED_HPP +#define TL_EXPECTED_HPP + +#define TL_EXPECTED_VERSION_MAJOR 1 +#define TL_EXPECTED_VERSION_MINOR 1 +#define TL_EXPECTED_VERSION_PATCH 0 + +#include +#include +#include +#include + +#if defined(__EXCEPTIONS) || defined(_CPPUNWIND) +#define TL_EXPECTED_EXCEPTIONS_ENABLED +#endif + +#if (defined(_MSC_VER) && _MSC_VER == 1900) +#define TL_EXPECTED_MSVC2015 +#define TL_EXPECTED_MSVC2015_CONSTEXPR +#else +#define TL_EXPECTED_MSVC2015_CONSTEXPR constexpr +#endif + +#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \ + !defined(__clang__)) +#define TL_EXPECTED_GCC49 +#endif + +#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && \ + !defined(__clang__)) +#define TL_EXPECTED_GCC54 +#endif + +#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && \ + !defined(__clang__)) +#define TL_EXPECTED_GCC55 +#endif + +#if !defined(TL_ASSERT) +//can't have assert in constexpr in C++11 and GCC 4.9 has a compiler bug +#if (__cplusplus > 201103L) && !defined(TL_EXPECTED_GCC49) +#include +#define TL_ASSERT(x) assert(x) +#else +#define TL_ASSERT(x) +#endif +#endif + +#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \ + !defined(__clang__)) +// GCC < 5 doesn't support overloading on const&& for member functions + +#define TL_EXPECTED_NO_CONSTRR +// GCC < 5 doesn't support some standard C++11 type traits +#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ + std::has_trivial_copy_constructor +#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ + std::has_trivial_copy_assign + +// This one will be different for GCC 5.7 if it's ever supported +#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \ + std::is_trivially_destructible + +// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks +// std::vector for non-copyable types +#elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__)) +#ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX +#define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX +namespace tl { +namespace detail { +template +struct is_trivially_copy_constructible + : std::is_trivially_copy_constructible {}; +#ifdef _GLIBCXX_VECTOR +template +struct is_trivially_copy_constructible> : std::false_type {}; +#endif +} // namespace detail +} // namespace tl +#endif + +#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ + tl::detail::is_trivially_copy_constructible +#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ + std::is_trivially_copy_assignable +#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \ + std::is_trivially_destructible +#else +#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ + std::is_trivially_copy_constructible +#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ + std::is_trivially_copy_assignable +#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \ + std::is_trivially_destructible +#endif + +#if __cplusplus > 201103L +#define TL_EXPECTED_CXX14 +#endif + +#ifdef TL_EXPECTED_GCC49 +#define TL_EXPECTED_GCC49_CONSTEXPR +#else +#define TL_EXPECTED_GCC49_CONSTEXPR constexpr +#endif + +#if (__cplusplus == 201103L || defined(TL_EXPECTED_MSVC2015) || \ + defined(TL_EXPECTED_GCC49)) +#define TL_EXPECTED_11_CONSTEXPR +#else +#define TL_EXPECTED_11_CONSTEXPR constexpr +#endif + +namespace tl { +template class expected; + +#ifndef TL_MONOSTATE_INPLACE_MUTEX +#define TL_MONOSTATE_INPLACE_MUTEX +class monostate {}; + +struct in_place_t { + explicit in_place_t() = default; +}; +static constexpr in_place_t in_place{}; +#endif + +template class unexpected { +public: + static_assert(!std::is_same::value, "E must not be void"); + + unexpected() = delete; + constexpr explicit unexpected(const E &e) : m_val(e) {} + + constexpr explicit unexpected(E &&e) : m_val(std::move(e)) {} + + template ::value>::type * = nullptr> + constexpr explicit unexpected(Args &&...args) + : m_val(std::forward(args)...) {} + template < + class U, class... Args, + typename std::enable_if &, Args &&...>::value>::type * = nullptr> + constexpr explicit unexpected(std::initializer_list l, Args &&...args) + : m_val(l, std::forward(args)...) {} + + constexpr const E &value() const & { return m_val; } + TL_EXPECTED_11_CONSTEXPR E &value() & { return m_val; } + TL_EXPECTED_11_CONSTEXPR E &&value() && { return std::move(m_val); } + constexpr const E &&value() const && { return std::move(m_val); } + +private: + E m_val; +}; + +#ifdef __cpp_deduction_guides +template unexpected(E) -> unexpected; +#endif + +template +constexpr bool operator==(const unexpected &lhs, const unexpected &rhs) { + return lhs.value() == rhs.value(); +} +template +constexpr bool operator!=(const unexpected &lhs, const unexpected &rhs) { + return lhs.value() != rhs.value(); +} +template +constexpr bool operator<(const unexpected &lhs, const unexpected &rhs) { + return lhs.value() < rhs.value(); +} +template +constexpr bool operator<=(const unexpected &lhs, const unexpected &rhs) { + return lhs.value() <= rhs.value(); +} +template +constexpr bool operator>(const unexpected &lhs, const unexpected &rhs) { + return lhs.value() > rhs.value(); +} +template +constexpr bool operator>=(const unexpected &lhs, const unexpected &rhs) { + return lhs.value() >= rhs.value(); +} + +template +unexpected::type> make_unexpected(E &&e) { + return unexpected::type>(std::forward(e)); +} + +struct unexpect_t { + unexpect_t() = default; +}; +static constexpr unexpect_t unexpect{}; + +namespace detail { +template +[[noreturn]] TL_EXPECTED_11_CONSTEXPR void throw_exception(E &&e) { +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + throw std::forward(e); +#else + (void)e; +#ifdef _MSC_VER + __assume(0); +#else + __builtin_unreachable(); +#endif +#endif +} + +#ifndef TL_TRAITS_MUTEX +#define TL_TRAITS_MUTEX +// C++14-style aliases for brevity +template using remove_const_t = typename std::remove_const::type; +template +using remove_reference_t = typename std::remove_reference::type; +template using decay_t = typename std::decay::type; +template +using enable_if_t = typename std::enable_if::type; +template +using conditional_t = typename std::conditional::type; + +// std::conjunction from C++17 +template struct conjunction : std::true_type {}; +template struct conjunction : B {}; +template +struct conjunction + : std::conditional, B>::type {}; + +#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L +#define TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND +#endif + +// In C++11 mode, there's an issue in libc++'s std::mem_fn +// which results in a hard-error when using it in a noexcept expression +// in some cases. This is a check to workaround the common failing case. +#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND +template +struct is_pointer_to_non_const_member_func : std::false_type {}; +template +struct is_pointer_to_non_const_member_func + : std::true_type {}; +template +struct is_pointer_to_non_const_member_func + : std::true_type {}; +template +struct is_pointer_to_non_const_member_func + : std::true_type {}; +template +struct is_pointer_to_non_const_member_func + : std::true_type {}; +template +struct is_pointer_to_non_const_member_func + : std::true_type {}; +template +struct is_pointer_to_non_const_member_func + : std::true_type {}; + +template struct is_const_or_const_ref : std::false_type {}; +template struct is_const_or_const_ref : std::true_type {}; +template struct is_const_or_const_ref : std::true_type {}; +#endif + +// std::invoke from C++17 +// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround +template < + typename Fn, typename... Args, +#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND + typename = enable_if_t::value && + is_const_or_const_ref::value)>, +#endif + typename = enable_if_t>::value>, int = 0> +constexpr auto invoke(Fn &&f, Args &&...args) noexcept( + noexcept(std::mem_fn(f)(std::forward(args)...))) + -> decltype(std::mem_fn(f)(std::forward(args)...)) { + return std::mem_fn(f)(std::forward(args)...); +} + +template >::value>> +constexpr auto invoke(Fn &&f, Args &&...args) noexcept( + noexcept(std::forward(f)(std::forward(args)...))) + -> decltype(std::forward(f)(std::forward(args)...)) { + return std::forward(f)(std::forward(args)...); +} + +// std::invoke_result from C++17 +template struct invoke_result_impl; + +template +struct invoke_result_impl< + F, + decltype(detail::invoke(std::declval(), std::declval()...), void()), + Us...> { + using type = + decltype(detail::invoke(std::declval(), std::declval()...)); +}; + +template +using invoke_result = invoke_result_impl; + +template +using invoke_result_t = typename invoke_result::type; + +#if defined(_MSC_VER) && _MSC_VER <= 1900 +// TODO make a version which works with MSVC 2015 +template struct is_swappable : std::true_type {}; + +template struct is_nothrow_swappable : std::true_type {}; +#else +// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept +namespace swap_adl_tests { +// if swap ADL finds this then it would call std::swap otherwise (same +// signature) +struct tag {}; + +template tag swap(T &, T &); +template tag swap(T (&a)[N], T (&b)[N]); + +// helper functions to test if an unqualified swap is possible, and if it +// becomes std::swap +template std::false_type can_swap(...) noexcept(false); +template (), std::declval()))> +std::true_type can_swap(int) noexcept(noexcept(swap(std::declval(), + std::declval()))); + +template std::false_type uses_std(...); +template +std::is_same(), std::declval())), tag> +uses_std(int); + +template +struct is_std_swap_noexcept + : std::integral_constant::value && + std::is_nothrow_move_assignable::value> {}; + +template +struct is_std_swap_noexcept : is_std_swap_noexcept {}; + +template +struct is_adl_swap_noexcept + : std::integral_constant(0))> {}; +} // namespace swap_adl_tests + +template +struct is_swappable + : std::integral_constant< + bool, + decltype(detail::swap_adl_tests::can_swap(0))::value && + (!decltype(detail::swap_adl_tests::uses_std(0))::value || + (std::is_move_assignable::value && + std::is_move_constructible::value))> {}; + +template +struct is_swappable + : std::integral_constant< + bool, + decltype(detail::swap_adl_tests::can_swap(0))::value && + (!decltype(detail::swap_adl_tests::uses_std( + 0))::value || + is_swappable::value)> {}; + +template +struct is_nothrow_swappable + : std::integral_constant< + bool, + is_swappable::value && + ((decltype(detail::swap_adl_tests::uses_std(0))::value && + detail::swap_adl_tests::is_std_swap_noexcept::value) || + (!decltype(detail::swap_adl_tests::uses_std(0))::value && + detail::swap_adl_tests::is_adl_swap_noexcept::value))> {}; +#endif +#endif + +// Trait for checking if a type is a tl::expected +template struct is_expected_impl : std::false_type {}; +template +struct is_expected_impl> : std::true_type {}; +template using is_expected = is_expected_impl>; + +template +using expected_enable_forward_value = detail::enable_if_t< + std::is_constructible::value && + !std::is_same, in_place_t>::value && + !std::is_same, detail::decay_t>::value && + !std::is_same, detail::decay_t>::value>; + +template +using expected_enable_from_other = detail::enable_if_t< + std::is_constructible::value && + std::is_constructible::value && + !std::is_constructible &>::value && + !std::is_constructible &&>::value && + !std::is_constructible &>::value && + !std::is_constructible &&>::value && + !std::is_convertible &, T>::value && + !std::is_convertible &&, T>::value && + !std::is_convertible &, T>::value && + !std::is_convertible &&, T>::value>; + +template +using is_void_or = conditional_t::value, std::true_type, U>; + +template +using is_copy_constructible_or_void = + is_void_or>; + +template +using is_move_constructible_or_void = + is_void_or>; + +template +using is_copy_assignable_or_void = is_void_or>; + +template +using is_move_assignable_or_void = is_void_or>; + +} // namespace detail + +namespace detail { +struct no_init_t {}; +static constexpr no_init_t no_init{}; + +// Implements the storage of the values, and ensures that the destructor is +// trivial if it can be. +// +// This specialization is for where neither `T` or `E` is trivially +// destructible, so the destructors must be called on destruction of the +// `expected` +template ::value, + bool = std::is_trivially_destructible::value> +struct expected_storage_base { + constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} + constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} + + template ::value> * = + nullptr> + constexpr expected_storage_base(in_place_t, Args &&...args) + : m_val(std::forward(args)...), m_has_val(true) {} + + template &, Args &&...>::value> * = nullptr> + constexpr expected_storage_base(in_place_t, std::initializer_list il, + Args &&...args) + : m_val(il, std::forward(args)...), m_has_val(true) {} + template ::value> * = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) + : m_unexpect(std::forward(args)...), m_has_val(false) {} + + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected_storage_base(unexpect_t, + std::initializer_list il, + Args &&...args) + : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + + ~expected_storage_base() { + if (m_has_val) { + m_val.~T(); + } else { + m_unexpect.~unexpected(); + } + } + union { + T m_val; + unexpected m_unexpect; + char m_no_init; + }; + bool m_has_val; +}; + +// This specialization is for when both `T` and `E` are trivially-destructible, +// so the destructor of the `expected` can be trivial. +template struct expected_storage_base { + constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} + constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} + + template ::value> * = + nullptr> + constexpr expected_storage_base(in_place_t, Args &&...args) + : m_val(std::forward(args)...), m_has_val(true) {} + + template &, Args &&...>::value> * = nullptr> + constexpr expected_storage_base(in_place_t, std::initializer_list il, + Args &&...args) + : m_val(il, std::forward(args)...), m_has_val(true) {} + template ::value> * = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) + : m_unexpect(std::forward(args)...), m_has_val(false) {} + + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected_storage_base(unexpect_t, + std::initializer_list il, + Args &&...args) + : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + + ~expected_storage_base() = default; + union { + T m_val; + unexpected m_unexpect; + char m_no_init; + }; + bool m_has_val; +}; + +// T is trivial, E is not. +template struct expected_storage_base { + constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} + TL_EXPECTED_MSVC2015_CONSTEXPR expected_storage_base(no_init_t) + : m_no_init(), m_has_val(false) {} + + template ::value> * = + nullptr> + constexpr expected_storage_base(in_place_t, Args &&...args) + : m_val(std::forward(args)...), m_has_val(true) {} + + template &, Args &&...>::value> * = nullptr> + constexpr expected_storage_base(in_place_t, std::initializer_list il, + Args &&...args) + : m_val(il, std::forward(args)...), m_has_val(true) {} + template ::value> * = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) + : m_unexpect(std::forward(args)...), m_has_val(false) {} + + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected_storage_base(unexpect_t, + std::initializer_list il, + Args &&...args) + : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + + ~expected_storage_base() { + if (!m_has_val) { + m_unexpect.~unexpected(); + } + } + + union { + T m_val; + unexpected m_unexpect; + char m_no_init; + }; + bool m_has_val; +}; + +// E is trivial, T is not. +template struct expected_storage_base { + constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} + constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} + + template ::value> * = + nullptr> + constexpr expected_storage_base(in_place_t, Args &&...args) + : m_val(std::forward(args)...), m_has_val(true) {} + + template &, Args &&...>::value> * = nullptr> + constexpr expected_storage_base(in_place_t, std::initializer_list il, + Args &&...args) + : m_val(il, std::forward(args)...), m_has_val(true) {} + template ::value> * = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) + : m_unexpect(std::forward(args)...), m_has_val(false) {} + + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected_storage_base(unexpect_t, + std::initializer_list il, + Args &&...args) + : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + + ~expected_storage_base() { + if (m_has_val) { + m_val.~T(); + } + } + union { + T m_val; + unexpected m_unexpect; + char m_no_init; + }; + bool m_has_val; +}; + +// `T` is `void`, `E` is trivially-destructible +template struct expected_storage_base { + #if __GNUC__ <= 5 + //no constexpr for GCC 4/5 bug + #else + TL_EXPECTED_MSVC2015_CONSTEXPR + #endif + expected_storage_base() : m_has_val(true) {} + + constexpr expected_storage_base(no_init_t) : m_val(), m_has_val(false) {} + + constexpr expected_storage_base(in_place_t) : m_has_val(true) {} + + template ::value> * = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) + : m_unexpect(std::forward(args)...), m_has_val(false) {} + + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected_storage_base(unexpect_t, + std::initializer_list il, + Args &&...args) + : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + + ~expected_storage_base() = default; + struct dummy {}; + union { + unexpected m_unexpect; + dummy m_val; + }; + bool m_has_val; +}; + +// `T` is `void`, `E` is not trivially-destructible +template struct expected_storage_base { + constexpr expected_storage_base() : m_dummy(), m_has_val(true) {} + constexpr expected_storage_base(no_init_t) : m_dummy(), m_has_val(false) {} + + constexpr expected_storage_base(in_place_t) : m_dummy(), m_has_val(true) {} + + template ::value> * = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) + : m_unexpect(std::forward(args)...), m_has_val(false) {} + + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected_storage_base(unexpect_t, + std::initializer_list il, + Args &&...args) + : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + + ~expected_storage_base() { + if (!m_has_val) { + m_unexpect.~unexpected(); + } + } + + union { + unexpected m_unexpect; + char m_dummy; + }; + bool m_has_val; +}; + +// This base class provides some handy member functions which can be used in +// further derived classes +template +struct expected_operations_base : expected_storage_base { + using expected_storage_base::expected_storage_base; + + template void construct(Args &&...args) noexcept { + new (std::addressof(this->m_val)) T(std::forward(args)...); + this->m_has_val = true; + } + + template void construct_with(Rhs &&rhs) noexcept { + new (std::addressof(this->m_val)) T(std::forward(rhs).get()); + this->m_has_val = true; + } + + template void construct_error(Args &&...args) noexcept { + new (std::addressof(this->m_unexpect)) + unexpected(std::forward(args)...); + this->m_has_val = false; + } + +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + + // These assign overloads ensure that the most efficient assignment + // implementation is used while maintaining the strong exception guarantee. + // The problematic case is where rhs has a value, but *this does not. + // + // This overload handles the case where we can just copy-construct `T` + // directly into place without throwing. + template ::value> + * = nullptr> + void assign(const expected_operations_base &rhs) noexcept { + if (!this->m_has_val && rhs.m_has_val) { + geterr().~unexpected(); + construct(rhs.get()); + } else { + assign_common(rhs); + } + } + + // This overload handles the case where we can attempt to create a copy of + // `T`, then no-throw move it into place if the copy was successful. + template ::value && + std::is_nothrow_move_constructible::value> + * = nullptr> + void assign(const expected_operations_base &rhs) noexcept { + if (!this->m_has_val && rhs.m_has_val) { + T tmp = rhs.get(); + geterr().~unexpected(); + construct(std::move(tmp)); + } else { + assign_common(rhs); + } + } + + // This overload is the worst-case, where we have to move-construct the + // unexpected value into temporary storage, then try to copy the T into place. + // If the construction succeeds, then everything is fine, but if it throws, + // then we move the old unexpected value back into place before rethrowing the + // exception. + template ::value && + !std::is_nothrow_move_constructible::value> + * = nullptr> + void assign(const expected_operations_base &rhs) { + if (!this->m_has_val && rhs.m_has_val) { + auto tmp = std::move(geterr()); + geterr().~unexpected(); + +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + try { + construct(rhs.get()); + } catch (...) { + geterr() = std::move(tmp); + throw; + } +#else + construct(rhs.get()); +#endif + } else { + assign_common(rhs); + } + } + + // These overloads do the same as above, but for rvalues + template ::value> + * = nullptr> + void assign(expected_operations_base &&rhs) noexcept { + if (!this->m_has_val && rhs.m_has_val) { + geterr().~unexpected(); + construct(std::move(rhs).get()); + } else { + assign_common(std::move(rhs)); + } + } + + template ::value> + * = nullptr> + void assign(expected_operations_base &&rhs) { + if (!this->m_has_val && rhs.m_has_val) { + auto tmp = std::move(geterr()); + geterr().~unexpected(); +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + try { + construct(std::move(rhs).get()); + } catch (...) { + geterr() = std::move(tmp); + throw; + } +#else + construct(std::move(rhs).get()); +#endif + } else { + assign_common(std::move(rhs)); + } + } + +#else + + // If exceptions are disabled then we can just copy-construct + void assign(const expected_operations_base &rhs) noexcept { + if (!this->m_has_val && rhs.m_has_val) { + geterr().~unexpected(); + construct(rhs.get()); + } else { + assign_common(rhs); + } + } + + void assign(expected_operations_base &&rhs) noexcept { + if (!this->m_has_val && rhs.m_has_val) { + geterr().~unexpected(); + construct(std::move(rhs).get()); + } else { + assign_common(std::move(rhs)); + } + } + +#endif + + // The common part of move/copy assigning + template void assign_common(Rhs &&rhs) { + if (this->m_has_val) { + if (rhs.m_has_val) { + get() = std::forward(rhs).get(); + } else { + destroy_val(); + construct_error(std::forward(rhs).geterr()); + } + } else { + if (!rhs.m_has_val) { + geterr() = std::forward(rhs).geterr(); + } + } + } + + bool has_value() const { return this->m_has_val; } + + TL_EXPECTED_11_CONSTEXPR T &get() & { return this->m_val; } + constexpr const T &get() const & { return this->m_val; } + TL_EXPECTED_11_CONSTEXPR T &&get() && { return std::move(this->m_val); } +#ifndef TL_EXPECTED_NO_CONSTRR + constexpr const T &&get() const && { return std::move(this->m_val); } +#endif + + TL_EXPECTED_11_CONSTEXPR unexpected &geterr() & { + return this->m_unexpect; + } + constexpr const unexpected &geterr() const & { return this->m_unexpect; } + TL_EXPECTED_11_CONSTEXPR unexpected &&geterr() && { + return std::move(this->m_unexpect); + } +#ifndef TL_EXPECTED_NO_CONSTRR + constexpr const unexpected &&geterr() const && { + return std::move(this->m_unexpect); + } +#endif + + TL_EXPECTED_11_CONSTEXPR void destroy_val() { get().~T(); } +}; + +// This base class provides some handy member functions which can be used in +// further derived classes +template +struct expected_operations_base : expected_storage_base { + using expected_storage_base::expected_storage_base; + + template void construct() noexcept { this->m_has_val = true; } + + // This function doesn't use its argument, but needs it so that code in + // levels above this can work independently of whether T is void + template void construct_with(Rhs &&) noexcept { + this->m_has_val = true; + } + + template void construct_error(Args &&...args) noexcept { + new (std::addressof(this->m_unexpect)) + unexpected(std::forward(args)...); + this->m_has_val = false; + } + + template void assign(Rhs &&rhs) noexcept { + if (!this->m_has_val) { + if (rhs.m_has_val) { + geterr().~unexpected(); + construct(); + } else { + geterr() = std::forward(rhs).geterr(); + } + } else { + if (!rhs.m_has_val) { + construct_error(std::forward(rhs).geterr()); + } + } + } + + bool has_value() const { return this->m_has_val; } + + TL_EXPECTED_11_CONSTEXPR unexpected &geterr() & { + return this->m_unexpect; + } + constexpr const unexpected &geterr() const & { return this->m_unexpect; } + TL_EXPECTED_11_CONSTEXPR unexpected &&geterr() && { + return std::move(this->m_unexpect); + } +#ifndef TL_EXPECTED_NO_CONSTRR + constexpr const unexpected &&geterr() const && { + return std::move(this->m_unexpect); + } +#endif + + TL_EXPECTED_11_CONSTEXPR void destroy_val() { + // no-op + } +}; + +// This class manages conditionally having a trivial copy constructor +// This specialization is for when T and E are trivially copy constructible +template :: + value &&TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value> +struct expected_copy_base : expected_operations_base { + using expected_operations_base::expected_operations_base; +}; + +// This specialization is for when T or E are not trivially copy constructible +template +struct expected_copy_base : expected_operations_base { + using expected_operations_base::expected_operations_base; + + expected_copy_base() = default; + expected_copy_base(const expected_copy_base &rhs) + : expected_operations_base(no_init) { + if (rhs.has_value()) { + this->construct_with(rhs); + } else { + this->construct_error(rhs.geterr()); + } + } + + expected_copy_base(expected_copy_base &&rhs) = default; + expected_copy_base &operator=(const expected_copy_base &rhs) = default; + expected_copy_base &operator=(expected_copy_base &&rhs) = default; +}; + +// This class manages conditionally having a trivial move constructor +// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it +// doesn't implement an analogue to std::is_trivially_move_constructible. We +// have to make do with a non-trivial move constructor even if T is trivially +// move constructible +#ifndef TL_EXPECTED_GCC49 +template >::value + &&std::is_trivially_move_constructible::value> +struct expected_move_base : expected_copy_base { + using expected_copy_base::expected_copy_base; +}; +#else +template struct expected_move_base; +#endif +template +struct expected_move_base : expected_copy_base { + using expected_copy_base::expected_copy_base; + + expected_move_base() = default; + expected_move_base(const expected_move_base &rhs) = default; + + expected_move_base(expected_move_base &&rhs) noexcept( + std::is_nothrow_move_constructible::value) + : expected_copy_base(no_init) { + if (rhs.has_value()) { + this->construct_with(std::move(rhs)); + } else { + this->construct_error(std::move(rhs.geterr())); + } + } + expected_move_base &operator=(const expected_move_base &rhs) = default; + expected_move_base &operator=(expected_move_base &&rhs) = default; +}; + +// This class manages conditionally having a trivial copy assignment operator +template >::value + &&TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value + &&TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value + &&TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value> +struct expected_copy_assign_base : expected_move_base { + using expected_move_base::expected_move_base; +}; + +template +struct expected_copy_assign_base : expected_move_base { + using expected_move_base::expected_move_base; + + expected_copy_assign_base() = default; + expected_copy_assign_base(const expected_copy_assign_base &rhs) = default; + + expected_copy_assign_base(expected_copy_assign_base &&rhs) = default; + expected_copy_assign_base &operator=(const expected_copy_assign_base &rhs) { + this->assign(rhs); + return *this; + } + expected_copy_assign_base & + operator=(expected_copy_assign_base &&rhs) = default; +}; + +// This class manages conditionally having a trivial move assignment operator +// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it +// doesn't implement an analogue to std::is_trivially_move_assignable. We have +// to make do with a non-trivial move assignment operator even if T is trivially +// move assignable +#ifndef TL_EXPECTED_GCC49 +template , + std::is_trivially_move_constructible, + std::is_trivially_move_assignable>>:: + value &&std::is_trivially_destructible::value + &&std::is_trivially_move_constructible::value + &&std::is_trivially_move_assignable::value> +struct expected_move_assign_base : expected_copy_assign_base { + using expected_copy_assign_base::expected_copy_assign_base; +}; +#else +template struct expected_move_assign_base; +#endif + +template +struct expected_move_assign_base + : expected_copy_assign_base { + using expected_copy_assign_base::expected_copy_assign_base; + + expected_move_assign_base() = default; + expected_move_assign_base(const expected_move_assign_base &rhs) = default; + + expected_move_assign_base(expected_move_assign_base &&rhs) = default; + + expected_move_assign_base & + operator=(const expected_move_assign_base &rhs) = default; + + expected_move_assign_base & + operator=(expected_move_assign_base &&rhs) noexcept( + std::is_nothrow_move_constructible::value + &&std::is_nothrow_move_assignable::value) { + this->assign(std::move(rhs)); + return *this; + } +}; + +// expected_delete_ctor_base will conditionally delete copy and move +// constructors depending on whether T is copy/move constructible +template ::value && + std::is_copy_constructible::value), + bool EnableMove = (is_move_constructible_or_void::value && + std::is_move_constructible::value)> +struct expected_delete_ctor_base { + expected_delete_ctor_base() = default; + expected_delete_ctor_base(const expected_delete_ctor_base &) = default; + expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default; + expected_delete_ctor_base & + operator=(const expected_delete_ctor_base &) = default; + expected_delete_ctor_base & + operator=(expected_delete_ctor_base &&) noexcept = default; +}; + +template +struct expected_delete_ctor_base { + expected_delete_ctor_base() = default; + expected_delete_ctor_base(const expected_delete_ctor_base &) = default; + expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete; + expected_delete_ctor_base & + operator=(const expected_delete_ctor_base &) = default; + expected_delete_ctor_base & + operator=(expected_delete_ctor_base &&) noexcept = default; +}; + +template +struct expected_delete_ctor_base { + expected_delete_ctor_base() = default; + expected_delete_ctor_base(const expected_delete_ctor_base &) = delete; + expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default; + expected_delete_ctor_base & + operator=(const expected_delete_ctor_base &) = default; + expected_delete_ctor_base & + operator=(expected_delete_ctor_base &&) noexcept = default; +}; + +template +struct expected_delete_ctor_base { + expected_delete_ctor_base() = default; + expected_delete_ctor_base(const expected_delete_ctor_base &) = delete; + expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete; + expected_delete_ctor_base & + operator=(const expected_delete_ctor_base &) = default; + expected_delete_ctor_base & + operator=(expected_delete_ctor_base &&) noexcept = default; +}; + +// expected_delete_assign_base will conditionally delete copy and move +// constructors depending on whether T and E are copy/move constructible + +// assignable +template ::value && + std::is_copy_constructible::value && + is_copy_assignable_or_void::value && + std::is_copy_assignable::value), + bool EnableMove = (is_move_constructible_or_void::value && + std::is_move_constructible::value && + is_move_assignable_or_void::value && + std::is_move_assignable::value)> +struct expected_delete_assign_base { + expected_delete_assign_base() = default; + expected_delete_assign_base(const expected_delete_assign_base &) = default; + expected_delete_assign_base(expected_delete_assign_base &&) noexcept = + default; + expected_delete_assign_base & + operator=(const expected_delete_assign_base &) = default; + expected_delete_assign_base & + operator=(expected_delete_assign_base &&) noexcept = default; +}; + +template +struct expected_delete_assign_base { + expected_delete_assign_base() = default; + expected_delete_assign_base(const expected_delete_assign_base &) = default; + expected_delete_assign_base(expected_delete_assign_base &&) noexcept = + default; + expected_delete_assign_base & + operator=(const expected_delete_assign_base &) = default; + expected_delete_assign_base & + operator=(expected_delete_assign_base &&) noexcept = delete; +}; + +template +struct expected_delete_assign_base { + expected_delete_assign_base() = default; + expected_delete_assign_base(const expected_delete_assign_base &) = default; + expected_delete_assign_base(expected_delete_assign_base &&) noexcept = + default; + expected_delete_assign_base & + operator=(const expected_delete_assign_base &) = delete; + expected_delete_assign_base & + operator=(expected_delete_assign_base &&) noexcept = default; +}; + +template +struct expected_delete_assign_base { + expected_delete_assign_base() = default; + expected_delete_assign_base(const expected_delete_assign_base &) = default; + expected_delete_assign_base(expected_delete_assign_base &&) noexcept = + default; + expected_delete_assign_base & + operator=(const expected_delete_assign_base &) = delete; + expected_delete_assign_base & + operator=(expected_delete_assign_base &&) noexcept = delete; +}; + +// This is needed to be able to construct the expected_default_ctor_base which +// follows, while still conditionally deleting the default constructor. +struct default_constructor_tag { + explicit constexpr default_constructor_tag() = default; +}; + +// expected_default_ctor_base will ensure that expected has a deleted default +// consturctor if T is not default constructible. +// This specialization is for when T is default constructible +template ::value || std::is_void::value> +struct expected_default_ctor_base { + constexpr expected_default_ctor_base() noexcept = default; + constexpr expected_default_ctor_base( + expected_default_ctor_base const &) noexcept = default; + constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept = + default; + expected_default_ctor_base & + operator=(expected_default_ctor_base const &) noexcept = default; + expected_default_ctor_base & + operator=(expected_default_ctor_base &&) noexcept = default; + + constexpr explicit expected_default_ctor_base(default_constructor_tag) {} +}; + +// This specialization is for when T is not default constructible +template struct expected_default_ctor_base { + constexpr expected_default_ctor_base() noexcept = delete; + constexpr expected_default_ctor_base( + expected_default_ctor_base const &) noexcept = default; + constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept = + default; + expected_default_ctor_base & + operator=(expected_default_ctor_base const &) noexcept = default; + expected_default_ctor_base & + operator=(expected_default_ctor_base &&) noexcept = default; + + constexpr explicit expected_default_ctor_base(default_constructor_tag) {} +}; +} // namespace detail + +template class bad_expected_access : public std::exception { +public: + explicit bad_expected_access(E e) : m_val(std::move(e)) {} + + virtual const char *what() const noexcept override { + return "Bad expected access"; + } + + const E &error() const & { return m_val; } + E &error() & { return m_val; } + const E &&error() const && { return std::move(m_val); } + E &&error() && { return std::move(m_val); } + +private: + E m_val; +}; + +/// An `expected` object is an object that contains the storage for +/// another object and manages the lifetime of this contained object `T`. +/// Alternatively it could contain the storage for another unexpected object +/// `E`. The contained object may not be initialized after the expected object +/// has been initialized, and may not be destroyed before the expected object +/// has been destroyed. The initialization state of the contained object is +/// tracked by the expected object. +template +class expected : private detail::expected_move_assign_base, + private detail::expected_delete_ctor_base, + private detail::expected_delete_assign_base, + private detail::expected_default_ctor_base { + static_assert(!std::is_reference::value, "T must not be a reference"); + static_assert(!std::is_same::type>::value, + "T must not be in_place_t"); + static_assert(!std::is_same::type>::value, + "T must not be unexpect_t"); + static_assert( + !std::is_same>::type>::value, + "T must not be unexpected"); + static_assert(!std::is_reference::value, "E must not be a reference"); + + T *valptr() { return std::addressof(this->m_val); } + const T *valptr() const { return std::addressof(this->m_val); } + unexpected *errptr() { return std::addressof(this->m_unexpect); } + const unexpected *errptr() const { + return std::addressof(this->m_unexpect); + } + + template ::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &val() { + return this->m_val; + } + TL_EXPECTED_11_CONSTEXPR unexpected &err() { return this->m_unexpect; } + + template ::value> * = nullptr> + constexpr const U &val() const { + return this->m_val; + } + constexpr const unexpected &err() const { return this->m_unexpect; } + + using impl_base = detail::expected_move_assign_base; + using ctor_base = detail::expected_default_ctor_base; + +public: + typedef T value_type; + typedef E error_type; + typedef unexpected unexpected_type; + +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ + !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) + template TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & { + return and_then_impl(*this, std::forward(f)); + } + template TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && { + return and_then_impl(std::move(*this), std::forward(f)); + } + template constexpr auto and_then(F &&f) const & { + return and_then_impl(*this, std::forward(f)); + } + +#ifndef TL_EXPECTED_NO_CONSTRR + template constexpr auto and_then(F &&f) const && { + return and_then_impl(std::move(*this), std::forward(f)); + } +#endif + +#else + template + TL_EXPECTED_11_CONSTEXPR auto + and_then(F &&f) & -> decltype(and_then_impl(std::declval(), + std::forward(f))) { + return and_then_impl(*this, std::forward(f)); + } + template + TL_EXPECTED_11_CONSTEXPR auto + and_then(F &&f) && -> decltype(and_then_impl(std::declval(), + std::forward(f))) { + return and_then_impl(std::move(*this), std::forward(f)); + } + template + constexpr auto and_then(F &&f) const & -> decltype(and_then_impl( + std::declval(), std::forward(f))) { + return and_then_impl(*this, std::forward(f)); + } + +#ifndef TL_EXPECTED_NO_CONSTRR + template + constexpr auto and_then(F &&f) const && -> decltype(and_then_impl( + std::declval(), std::forward(f))) { + return and_then_impl(std::move(*this), std::forward(f)); + } +#endif +#endif + +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ + !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) + template TL_EXPECTED_11_CONSTEXPR auto map(F &&f) & { + return expected_map_impl(*this, std::forward(f)); + } + template TL_EXPECTED_11_CONSTEXPR auto map(F &&f) && { + return expected_map_impl(std::move(*this), std::forward(f)); + } + template constexpr auto map(F &&f) const & { + return expected_map_impl(*this, std::forward(f)); + } + template constexpr auto map(F &&f) const && { + return expected_map_impl(std::move(*this), std::forward(f)); + } +#else + template + TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl( + std::declval(), std::declval())) + map(F &&f) & { + return expected_map_impl(*this, std::forward(f)); + } + template + TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval(), + std::declval())) + map(F &&f) && { + return expected_map_impl(std::move(*this), std::forward(f)); + } + template + constexpr decltype(expected_map_impl(std::declval(), + std::declval())) + map(F &&f) const & { + return expected_map_impl(*this, std::forward(f)); + } + +#ifndef TL_EXPECTED_NO_CONSTRR + template + constexpr decltype(expected_map_impl(std::declval(), + std::declval())) + map(F &&f) const && { + return expected_map_impl(std::move(*this), std::forward(f)); + } +#endif +#endif + +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ + !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) + template TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) & { + return expected_map_impl(*this, std::forward(f)); + } + template TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) && { + return expected_map_impl(std::move(*this), std::forward(f)); + } + template constexpr auto transform(F &&f) const & { + return expected_map_impl(*this, std::forward(f)); + } + template constexpr auto transform(F &&f) const && { + return expected_map_impl(std::move(*this), std::forward(f)); + } +#else + template + TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl( + std::declval(), std::declval())) + transform(F &&f) & { + return expected_map_impl(*this, std::forward(f)); + } + template + TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval(), + std::declval())) + transform(F &&f) && { + return expected_map_impl(std::move(*this), std::forward(f)); + } + template + constexpr decltype(expected_map_impl(std::declval(), + std::declval())) + transform(F &&f) const & { + return expected_map_impl(*this, std::forward(f)); + } + +#ifndef TL_EXPECTED_NO_CONSTRR + template + constexpr decltype(expected_map_impl(std::declval(), + std::declval())) + transform(F &&f) const && { + return expected_map_impl(std::move(*this), std::forward(f)); + } +#endif +#endif + +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ + !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) + template TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) & { + return map_error_impl(*this, std::forward(f)); + } + template TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) && { + return map_error_impl(std::move(*this), std::forward(f)); + } + template constexpr auto map_error(F &&f) const & { + return map_error_impl(*this, std::forward(f)); + } + template constexpr auto map_error(F &&f) const && { + return map_error_impl(std::move(*this), std::forward(f)); + } +#else + template + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) & { + return map_error_impl(*this, std::forward(f)); + } + template + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) && { + return map_error_impl(std::move(*this), std::forward(f)); + } + template + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) const & { + return map_error_impl(*this, std::forward(f)); + } + +#ifndef TL_EXPECTED_NO_CONSTRR + template + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) const && { + return map_error_impl(std::move(*this), std::forward(f)); + } +#endif +#endif +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ + !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) + template TL_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) & { + return map_error_impl(*this, std::forward(f)); + } + template TL_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) && { + return map_error_impl(std::move(*this), std::forward(f)); + } + template constexpr auto transform_error(F &&f) const & { + return map_error_impl(*this, std::forward(f)); + } + template constexpr auto transform_error(F &&f) const && { + return map_error_impl(std::move(*this), std::forward(f)); + } +#else + template + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F &&f) & { + return map_error_impl(*this, std::forward(f)); + } + template + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F &&f) && { + return map_error_impl(std::move(*this), std::forward(f)); + } + template + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F &&f) const & { + return map_error_impl(*this, std::forward(f)); + } + +#ifndef TL_EXPECTED_NO_CONSTRR + template + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F &&f) const && { + return map_error_impl(std::move(*this), std::forward(f)); + } +#endif +#endif + template expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) & { + return or_else_impl(*this, std::forward(f)); + } + + template expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) && { + return or_else_impl(std::move(*this), std::forward(f)); + } + + template expected constexpr or_else(F &&f) const & { + return or_else_impl(*this, std::forward(f)); + } + +#ifndef TL_EXPECTED_NO_CONSTRR + template expected constexpr or_else(F &&f) const && { + return or_else_impl(std::move(*this), std::forward(f)); + } +#endif + constexpr expected() = default; + constexpr expected(const expected &rhs) = default; + constexpr expected(expected &&rhs) = default; + expected &operator=(const expected &rhs) = default; + expected &operator=(expected &&rhs) = default; + + template ::value> * = + nullptr> + constexpr expected(in_place_t, Args &&...args) + : impl_base(in_place, std::forward(args)...), + ctor_base(detail::default_constructor_tag{}) {} + + template &, Args &&...>::value> * = nullptr> + constexpr expected(in_place_t, std::initializer_list il, Args &&...args) + : impl_base(in_place, il, std::forward(args)...), + ctor_base(detail::default_constructor_tag{}) {} + + template ::value> * = + nullptr, + detail::enable_if_t::value> * = + nullptr> + explicit constexpr expected(const unexpected &e) + : impl_base(unexpect, e.value()), + ctor_base(detail::default_constructor_tag{}) {} + + template < + class G = E, + detail::enable_if_t::value> * = + nullptr, + detail::enable_if_t::value> * = nullptr> + constexpr expected(unexpected const &e) + : impl_base(unexpect, e.value()), + ctor_base(detail::default_constructor_tag{}) {} + + template < + class G = E, + detail::enable_if_t::value> * = nullptr, + detail::enable_if_t::value> * = nullptr> + explicit constexpr expected(unexpected &&e) noexcept( + std::is_nothrow_constructible::value) + : impl_base(unexpect, std::move(e.value())), + ctor_base(detail::default_constructor_tag{}) {} + + template < + class G = E, + detail::enable_if_t::value> * = nullptr, + detail::enable_if_t::value> * = nullptr> + constexpr expected(unexpected &&e) noexcept( + std::is_nothrow_constructible::value) + : impl_base(unexpect, std::move(e.value())), + ctor_base(detail::default_constructor_tag{}) {} + + template ::value> * = + nullptr> + constexpr explicit expected(unexpect_t, Args &&...args) + : impl_base(unexpect, std::forward(args)...), + ctor_base(detail::default_constructor_tag{}) {} + + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected(unexpect_t, std::initializer_list il, + Args &&...args) + : impl_base(unexpect, il, std::forward(args)...), + ctor_base(detail::default_constructor_tag{}) {} + + template ::value && + std::is_convertible::value)> * = + nullptr, + detail::expected_enable_from_other + * = nullptr> + explicit TL_EXPECTED_11_CONSTEXPR expected(const expected &rhs) + : ctor_base(detail::default_constructor_tag{}) { + if (rhs.has_value()) { + this->construct(*rhs); + } else { + this->construct_error(rhs.error()); + } + } + + template ::value && + std::is_convertible::value)> * = + nullptr, + detail::expected_enable_from_other + * = nullptr> + TL_EXPECTED_11_CONSTEXPR expected(const expected &rhs) + : ctor_base(detail::default_constructor_tag{}) { + if (rhs.has_value()) { + this->construct(*rhs); + } else { + this->construct_error(rhs.error()); + } + } + + template < + class U, class G, + detail::enable_if_t::value && + std::is_convertible::value)> * = nullptr, + detail::expected_enable_from_other * = nullptr> + explicit TL_EXPECTED_11_CONSTEXPR expected(expected &&rhs) + : ctor_base(detail::default_constructor_tag{}) { + if (rhs.has_value()) { + this->construct(std::move(*rhs)); + } else { + this->construct_error(std::move(rhs.error())); + } + } + + template < + class U, class G, + detail::enable_if_t<(std::is_convertible::value && + std::is_convertible::value)> * = nullptr, + detail::expected_enable_from_other * = nullptr> + TL_EXPECTED_11_CONSTEXPR expected(expected &&rhs) + : ctor_base(detail::default_constructor_tag{}) { + if (rhs.has_value()) { + this->construct(std::move(*rhs)); + } else { + this->construct_error(std::move(rhs.error())); + } + } + + template < + class U = T, + detail::enable_if_t::value> * = nullptr, + detail::expected_enable_forward_value * = nullptr> + explicit TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v) + : expected(in_place, std::forward(v)) {} + + template < + class U = T, + detail::enable_if_t::value> * = nullptr, + detail::expected_enable_forward_value * = nullptr> + TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v) + : expected(in_place, std::forward(v)) {} + + template < + class U = T, class G = T, + detail::enable_if_t::value> * = + nullptr, + detail::enable_if_t::value> * = nullptr, + detail::enable_if_t< + (!std::is_same, detail::decay_t>::value && + !detail::conjunction, + std::is_same>>::value && + std::is_constructible::value && + std::is_assignable::value && + std::is_nothrow_move_constructible::value)> * = nullptr> + expected &operator=(U &&v) { + if (has_value()) { + val() = std::forward(v); + } else { + err().~unexpected(); + ::new (valptr()) T(std::forward(v)); + this->m_has_val = true; + } + + return *this; + } + + template < + class U = T, class G = T, + detail::enable_if_t::value> * = + nullptr, + detail::enable_if_t::value> * = nullptr, + detail::enable_if_t< + (!std::is_same, detail::decay_t>::value && + !detail::conjunction, + std::is_same>>::value && + std::is_constructible::value && + std::is_assignable::value && + std::is_nothrow_move_constructible::value)> * = nullptr> + expected &operator=(U &&v) { + if (has_value()) { + val() = std::forward(v); + } else { + auto tmp = std::move(err()); + err().~unexpected(); + +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + try { + ::new (valptr()) T(std::forward(v)); + this->m_has_val = true; + } catch (...) { + err() = std::move(tmp); + throw; + } +#else + ::new (valptr()) T(std::forward(v)); + this->m_has_val = true; +#endif + } + + return *this; + } + + template ::value && + std::is_assignable::value> * = nullptr> + expected &operator=(const unexpected &rhs) { + if (!has_value()) { + err() = rhs; + } else { + this->destroy_val(); + ::new (errptr()) unexpected(rhs); + this->m_has_val = false; + } + + return *this; + } + + template ::value && + std::is_move_assignable::value> * = nullptr> + expected &operator=(unexpected &&rhs) noexcept { + if (!has_value()) { + err() = std::move(rhs); + } else { + this->destroy_val(); + ::new (errptr()) unexpected(std::move(rhs)); + this->m_has_val = false; + } + + return *this; + } + + template ::value> * = nullptr> + void emplace(Args &&...args) { + if (has_value()) { + val().~T(); + } else { + err().~unexpected(); + this->m_has_val = true; + } + ::new (valptr()) T(std::forward(args)...); + } + + template ::value> * = nullptr> + void emplace(Args &&...args) { + if (has_value()) { + val().~T(); + ::new (valptr()) T(std::forward(args)...); + } else { + auto tmp = std::move(err()); + err().~unexpected(); + +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + try { + ::new (valptr()) T(std::forward(args)...); + this->m_has_val = true; + } catch (...) { + err() = std::move(tmp); + throw; + } +#else + ::new (valptr()) T(std::forward(args)...); + this->m_has_val = true; +#endif + } + } + + template &, Args &&...>::value> * = nullptr> + void emplace(std::initializer_list il, Args &&...args) { + if (has_value()) { + T t(il, std::forward(args)...); + val() = std::move(t); + } else { + err().~unexpected(); + ::new (valptr()) T(il, std::forward(args)...); + this->m_has_val = true; + } + } + + template &, Args &&...>::value> * = nullptr> + void emplace(std::initializer_list il, Args &&...args) { + if (has_value()) { + T t(il, std::forward(args)...); + val() = std::move(t); + } else { + auto tmp = std::move(err()); + err().~unexpected(); + +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + try { + ::new (valptr()) T(il, std::forward(args)...); + this->m_has_val = true; + } catch (...) { + err() = std::move(tmp); + throw; + } +#else + ::new (valptr()) T(il, std::forward(args)...); + this->m_has_val = true; +#endif + } + } + +private: + using t_is_void = std::true_type; + using t_is_not_void = std::false_type; + using t_is_nothrow_move_constructible = std::true_type; + using move_constructing_t_can_throw = std::false_type; + using e_is_nothrow_move_constructible = std::true_type; + using move_constructing_e_can_throw = std::false_type; + + void swap_where_both_have_value(expected & /*rhs*/, t_is_void) noexcept { + // swapping void is a no-op + } + + void swap_where_both_have_value(expected &rhs, t_is_not_void) { + using std::swap; + swap(val(), rhs.val()); + } + + void swap_where_only_one_has_value(expected &rhs, t_is_void) noexcept( + std::is_nothrow_move_constructible::value) { + ::new (errptr()) unexpected_type(std::move(rhs.err())); + rhs.err().~unexpected_type(); + std::swap(this->m_has_val, rhs.m_has_val); + } + + void swap_where_only_one_has_value(expected &rhs, t_is_not_void) { + swap_where_only_one_has_value_and_t_is_not_void( + rhs, typename std::is_nothrow_move_constructible::type{}, + typename std::is_nothrow_move_constructible::type{}); + } + + void swap_where_only_one_has_value_and_t_is_not_void( + expected &rhs, t_is_nothrow_move_constructible, + e_is_nothrow_move_constructible) noexcept { + auto temp = std::move(val()); + val().~T(); + ::new (errptr()) unexpected_type(std::move(rhs.err())); + rhs.err().~unexpected_type(); + ::new (rhs.valptr()) T(std::move(temp)); + std::swap(this->m_has_val, rhs.m_has_val); + } + + void swap_where_only_one_has_value_and_t_is_not_void( + expected &rhs, t_is_nothrow_move_constructible, + move_constructing_e_can_throw) { + auto temp = std::move(val()); + val().~T(); +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + try { + ::new (errptr()) unexpected_type(std::move(rhs.err())); + rhs.err().~unexpected_type(); + ::new (rhs.valptr()) T(std::move(temp)); + std::swap(this->m_has_val, rhs.m_has_val); + } catch (...) { + val() = std::move(temp); + throw; + } +#else + ::new (errptr()) unexpected_type(std::move(rhs.err())); + rhs.err().~unexpected_type(); + ::new (rhs.valptr()) T(std::move(temp)); + std::swap(this->m_has_val, rhs.m_has_val); +#endif + } + + void swap_where_only_one_has_value_and_t_is_not_void( + expected &rhs, move_constructing_t_can_throw, + e_is_nothrow_move_constructible) { + auto temp = std::move(rhs.err()); + rhs.err().~unexpected_type(); +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + try { + ::new (rhs.valptr()) T(std::move(val())); + val().~T(); + ::new (errptr()) unexpected_type(std::move(temp)); + std::swap(this->m_has_val, rhs.m_has_val); + } catch (...) { + rhs.err() = std::move(temp); + throw; + } +#else + ::new (rhs.valptr()) T(std::move(val())); + val().~T(); + ::new (errptr()) unexpected_type(std::move(temp)); + std::swap(this->m_has_val, rhs.m_has_val); +#endif + } + +public: + template + detail::enable_if_t::value && + detail::is_swappable::value && + (std::is_nothrow_move_constructible::value || + std::is_nothrow_move_constructible::value)> + swap(expected &rhs) noexcept( + std::is_nothrow_move_constructible::value + &&detail::is_nothrow_swappable::value + &&std::is_nothrow_move_constructible::value + &&detail::is_nothrow_swappable::value) { + if (has_value() && rhs.has_value()) { + swap_where_both_have_value(rhs, typename std::is_void::type{}); + } else if (!has_value() && rhs.has_value()) { + rhs.swap(*this); + } else if (has_value()) { + swap_where_only_one_has_value(rhs, typename std::is_void::type{}); + } else { + using std::swap; + swap(err(), rhs.err()); + } + } + + constexpr const T *operator->() const { + TL_ASSERT(has_value()); + return valptr(); + } + TL_EXPECTED_11_CONSTEXPR T *operator->() { + TL_ASSERT(has_value()); + return valptr(); + } + + template ::value> * = nullptr> + constexpr const U &operator*() const & { + TL_ASSERT(has_value()); + return val(); + } + template ::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &operator*() & { + TL_ASSERT(has_value()); + return val(); + } + template ::value> * = nullptr> + constexpr const U &&operator*() const && { + TL_ASSERT(has_value()); + return std::move(val()); + } + template ::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &&operator*() && { + TL_ASSERT(has_value()); + return std::move(val()); + } + + constexpr bool has_value() const noexcept { return this->m_has_val; } + constexpr explicit operator bool() const noexcept { return this->m_has_val; } + + template ::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR const U &value() const & { + if (!has_value()) + detail::throw_exception(bad_expected_access(err().value())); + return val(); + } + template ::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &value() & { + if (!has_value()) + detail::throw_exception(bad_expected_access(err().value())); + return val(); + } + template ::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR const U &&value() const && { + if (!has_value()) + detail::throw_exception(bad_expected_access(std::move(err()).value())); + return std::move(val()); + } + template ::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &&value() && { + if (!has_value()) + detail::throw_exception(bad_expected_access(std::move(err()).value())); + return std::move(val()); + } + + constexpr const E &error() const & { + TL_ASSERT(!has_value()); + return err().value(); + } + TL_EXPECTED_11_CONSTEXPR E &error() & { + TL_ASSERT(!has_value()); + return err().value(); + } + constexpr const E &&error() const && { + TL_ASSERT(!has_value()); + return std::move(err().value()); + } + TL_EXPECTED_11_CONSTEXPR E &&error() && { + TL_ASSERT(!has_value()); + return std::move(err().value()); + } + + template constexpr T value_or(U &&v) const & { + static_assert(std::is_copy_constructible::value && + std::is_convertible::value, + "T must be copy-constructible and convertible to from U&&"); + return bool(*this) ? **this : static_cast(std::forward(v)); + } + template TL_EXPECTED_11_CONSTEXPR T value_or(U &&v) && { + static_assert(std::is_move_constructible::value && + std::is_convertible::value, + "T must be move-constructible and convertible to from U&&"); + return bool(*this) ? std::move(**this) : static_cast(std::forward(v)); + } +}; + +namespace detail { +template using exp_t = typename detail::decay_t::value_type; +template using err_t = typename detail::decay_t::error_type; +template using ret_t = expected>; + +#ifdef TL_EXPECTED_CXX14 +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + *std::declval()))> +constexpr auto and_then_impl(Exp &&exp, F &&f) { + static_assert(detail::is_expected::value, "F must return an expected"); + + return exp.has_value() + ? detail::invoke(std::forward(f), *std::forward(exp)) + : Ret(unexpect, std::forward(exp).error()); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval()))> +constexpr auto and_then_impl(Exp &&exp, F &&f) { + static_assert(detail::is_expected::value, "F must return an expected"); + + return exp.has_value() ? detail::invoke(std::forward(f)) + : Ret(unexpect, std::forward(exp).error()); +} +#else +template struct TC; +template (), + *std::declval())), + detail::enable_if_t>::value> * = nullptr> +auto and_then_impl(Exp &&exp, F &&f) -> Ret { + static_assert(detail::is_expected::value, "F must return an expected"); + + return exp.has_value() + ? detail::invoke(std::forward(f), *std::forward(exp)) + : Ret(unexpect, std::forward(exp).error()); +} + +template ())), + detail::enable_if_t>::value> * = nullptr> +constexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret { + static_assert(detail::is_expected::value, "F must return an expected"); + + return exp.has_value() ? detail::invoke(std::forward(f)) + : Ret(unexpect, std::forward(exp).error()); +} +#endif + +#ifdef TL_EXPECTED_CXX14 +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + *std::declval())), + detail::enable_if_t::value> * = nullptr> +constexpr auto expected_map_impl(Exp &&exp, F &&f) { + using result = ret_t>; + return exp.has_value() ? result(detail::invoke(std::forward(f), + *std::forward(exp))) + : result(unexpect, std::forward(exp).error()); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + *std::declval())), + detail::enable_if_t::value> * = nullptr> +auto expected_map_impl(Exp &&exp, F &&f) { + using result = expected>; + if (exp.has_value()) { + detail::invoke(std::forward(f), *std::forward(exp)); + return result(); + } + + return result(unexpect, std::forward(exp).error()); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval())), + detail::enable_if_t::value> * = nullptr> +constexpr auto expected_map_impl(Exp &&exp, F &&f) { + using result = ret_t>; + return exp.has_value() ? result(detail::invoke(std::forward(f))) + : result(unexpect, std::forward(exp).error()); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval())), + detail::enable_if_t::value> * = nullptr> +auto expected_map_impl(Exp &&exp, F &&f) { + using result = expected>; + if (exp.has_value()) { + detail::invoke(std::forward(f)); + return result(); + } + + return result(unexpect, std::forward(exp).error()); +} +#else +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + *std::declval())), + detail::enable_if_t::value> * = nullptr> + +constexpr auto expected_map_impl(Exp &&exp, F &&f) + -> ret_t> { + using result = ret_t>; + + return exp.has_value() ? result(detail::invoke(std::forward(f), + *std::forward(exp))) + : result(unexpect, std::forward(exp).error()); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + *std::declval())), + detail::enable_if_t::value> * = nullptr> + +auto expected_map_impl(Exp &&exp, F &&f) -> expected> { + if (exp.has_value()) { + detail::invoke(std::forward(f), *std::forward(exp)); + return {}; + } + + return unexpected>(std::forward(exp).error()); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval())), + detail::enable_if_t::value> * = nullptr> + +constexpr auto expected_map_impl(Exp &&exp, F &&f) + -> ret_t> { + using result = ret_t>; + + return exp.has_value() ? result(detail::invoke(std::forward(f))) + : result(unexpect, std::forward(exp).error()); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval())), + detail::enable_if_t::value> * = nullptr> + +auto expected_map_impl(Exp &&exp, F &&f) -> expected> { + if (exp.has_value()) { + detail::invoke(std::forward(f)); + return {}; + } + + return unexpected>(std::forward(exp).error()); +} +#endif + +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ + !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +constexpr auto map_error_impl(Exp &&exp, F &&f) { + using result = expected, detail::decay_t>; + return exp.has_value() + ? result(*std::forward(exp)) + : result(unexpect, detail::invoke(std::forward(f), + std::forward(exp).error())); +} +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +auto map_error_impl(Exp &&exp, F &&f) { + using result = expected, monostate>; + if (exp.has_value()) { + return result(*std::forward(exp)); + } + + detail::invoke(std::forward(f), std::forward(exp).error()); + return result(unexpect, monostate{}); +} +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +constexpr auto map_error_impl(Exp &&exp, F &&f) { + using result = expected, detail::decay_t>; + return exp.has_value() + ? result() + : result(unexpect, detail::invoke(std::forward(f), + std::forward(exp).error())); +} +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +auto map_error_impl(Exp &&exp, F &&f) { + using result = expected, monostate>; + if (exp.has_value()) { + return result(); + } + + detail::invoke(std::forward(f), std::forward(exp).error()); + return result(unexpect, monostate{}); +} +#else +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +constexpr auto map_error_impl(Exp &&exp, F &&f) + -> expected, detail::decay_t> { + using result = expected, detail::decay_t>; + + return exp.has_value() + ? result(*std::forward(exp)) + : result(unexpect, detail::invoke(std::forward(f), + std::forward(exp).error())); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +auto map_error_impl(Exp &&exp, F &&f) -> expected, monostate> { + using result = expected, monostate>; + if (exp.has_value()) { + return result(*std::forward(exp)); + } + + detail::invoke(std::forward(f), std::forward(exp).error()); + return result(unexpect, monostate{}); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +constexpr auto map_error_impl(Exp &&exp, F &&f) + -> expected, detail::decay_t> { + using result = expected, detail::decay_t>; + + return exp.has_value() + ? result() + : result(unexpect, detail::invoke(std::forward(f), + std::forward(exp).error())); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +auto map_error_impl(Exp &&exp, F &&f) -> expected, monostate> { + using result = expected, monostate>; + if (exp.has_value()) { + return result(); + } + + detail::invoke(std::forward(f), std::forward(exp).error()); + return result(unexpect, monostate{}); +} +#endif + +#ifdef TL_EXPECTED_CXX14 +template (), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +constexpr auto or_else_impl(Exp &&exp, F &&f) { + static_assert(detail::is_expected::value, "F must return an expected"); + return exp.has_value() ? std::forward(exp) + : detail::invoke(std::forward(f), + std::forward(exp).error()); +} + +template (), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +detail::decay_t or_else_impl(Exp &&exp, F &&f) { + return exp.has_value() ? std::forward(exp) + : (detail::invoke(std::forward(f), + std::forward(exp).error()), + std::forward(exp)); +} +#else +template (), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +auto or_else_impl(Exp &&exp, F &&f) -> Ret { + static_assert(detail::is_expected::value, "F must return an expected"); + return exp.has_value() ? std::forward(exp) + : detail::invoke(std::forward(f), + std::forward(exp).error()); +} + +template (), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +detail::decay_t or_else_impl(Exp &&exp, F &&f) { + return exp.has_value() ? std::forward(exp) + : (detail::invoke(std::forward(f), + std::forward(exp).error()), + std::forward(exp)); +} +#endif +} // namespace detail + +template +constexpr bool operator==(const expected &lhs, + const expected &rhs) { + return (lhs.has_value() != rhs.has_value()) + ? false + : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs); +} +template +constexpr bool operator!=(const expected &lhs, + const expected &rhs) { + return (lhs.has_value() != rhs.has_value()) + ? true + : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs); +} +template +constexpr bool operator==(const expected &lhs, + const expected &rhs) { + return (lhs.has_value() != rhs.has_value()) + ? false + : (!lhs.has_value() ? lhs.error() == rhs.error() : true); +} +template +constexpr bool operator!=(const expected &lhs, + const expected &rhs) { + return (lhs.has_value() != rhs.has_value()) + ? true + : (!lhs.has_value() ? lhs.error() == rhs.error() : false); +} + +template +constexpr bool operator==(const expected &x, const U &v) { + return x.has_value() ? *x == v : false; +} +template +constexpr bool operator==(const U &v, const expected &x) { + return x.has_value() ? *x == v : false; +} +template +constexpr bool operator!=(const expected &x, const U &v) { + return x.has_value() ? *x != v : true; +} +template +constexpr bool operator!=(const U &v, const expected &x) { + return x.has_value() ? *x != v : true; +} + +template +constexpr bool operator==(const expected &x, const unexpected &e) { + return x.has_value() ? false : x.error() == e.value(); +} +template +constexpr bool operator==(const unexpected &e, const expected &x) { + return x.has_value() ? false : x.error() == e.value(); +} +template +constexpr bool operator!=(const expected &x, const unexpected &e) { + return x.has_value() ? true : x.error() != e.value(); +} +template +constexpr bool operator!=(const unexpected &e, const expected &x) { + return x.has_value() ? true : x.error() != e.value(); +} + +template ::value || + std::is_move_constructible::value) && + detail::is_swappable::value && + std::is_move_constructible::value && + detail::is_swappable::value> * = nullptr> +void swap(expected &lhs, + expected &rhs) noexcept(noexcept(lhs.swap(rhs))) { + lhs.swap(rhs); +} +} // namespace tl + +#endif diff --git a/YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.cpp b/YUViewLib/externalLibs/LibFFmpeg++/common/FFMpegLibrariesTypes.cpp similarity index 98% rename from YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.cpp rename to YUViewLib/externalLibs/LibFFmpeg++/common/FFMpegLibrariesTypes.cpp index 35db05f10..6a2f093c7 100644 --- a/YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.cpp +++ b/YUViewLib/externalLibs/LibFFmpeg++/common/FFMpegLibrariesTypes.cpp @@ -32,7 +32,7 @@ #include "FFMpegLibrariesTypes.h" -namespace FFmpeg +namespace LibFFmpeg { QString timestampToString(int64_t timestamp, AVRational timebase) @@ -81,4 +81,4 @@ std::ostream &operator<<(std::ostream &stream, const Version &version) return stream; } -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.h b/YUViewLib/externalLibs/LibFFmpeg++/common/FFMpegLibrariesTypes.h similarity index 99% rename from YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.h rename to YUViewLib/externalLibs/LibFFmpeg++/common/FFMpegLibrariesTypes.h index 2be7dd215..0026d9145 100644 --- a/YUViewLib/src/ffmpeg/FFMpegLibrariesTypes.h +++ b/YUViewLib/externalLibs/LibFFmpeg++/common/FFMpegLibrariesTypes.h @@ -44,9 +44,11 @@ * from the FFmpeg public API headers. Please see (www.ffmpeg.org). */ -namespace FFmpeg +namespace LibFFmpeg { +using Log = std::vector; + // Some structs/enums which actual definition does not interest us. struct AVFormatContext; struct AVClass; @@ -403,7 +405,7 @@ struct Version std::optional micro{}; }; -std::string to_string(const Version &version); +std::string to_string(const Version &version); std::ostream &operator<<(std::ostream &stream, const Version &version); struct LibraryVersions @@ -416,4 +418,4 @@ struct LibraryVersions QString timestampToString(int64_t timestamp, AVRational timebase); -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/MotionVector.cpp b/YUViewLib/externalLibs/LibFFmpeg++/common/MotionVector.cpp similarity index 98% rename from YUViewLib/src/ffmpeg/MotionVector.cpp rename to YUViewLib/externalLibs/LibFFmpeg++/common/MotionVector.cpp index 8130a4656..20b260f83 100644 --- a/YUViewLib/src/ffmpeg/MotionVector.cpp +++ b/YUViewLib/externalLibs/LibFFmpeg++/common/MotionVector.cpp @@ -33,7 +33,7 @@ #include "MotionVector.h" #include -namespace FFmpeg +namespace LibFFmpeg { namespace @@ -119,4 +119,4 @@ parseMotionData(const LibraryVersions &libraryVersions, const uint8_t *data, con throw std::runtime_error("Invalid library version"); } -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/MotionVector.h b/YUViewLib/externalLibs/LibFFmpeg++/common/MotionVector.h similarity index 97% rename from YUViewLib/src/ffmpeg/MotionVector.h rename to YUViewLib/externalLibs/LibFFmpeg++/common/MotionVector.h index 7941b2420..bc8d7a221 100644 --- a/YUViewLib/src/ffmpeg/MotionVector.h +++ b/YUViewLib/externalLibs/LibFFmpeg++/common/MotionVector.h @@ -34,7 +34,7 @@ #include "FFMpegLibrariesTypes.h" -namespace FFmpeg +namespace LibFFmpeg { struct MotionVector @@ -56,4 +56,4 @@ struct MotionVector std::vector parseMotionData(const LibraryVersions &libraryVersions, const uint8_t *data, const size_t dataSize); -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/externalLibs/LibFFmpeg++/libFFmpeg++.pro b/YUViewLib/externalLibs/LibFFmpeg++/libFFmpeg++.pro new file mode 100644 index 000000000..2f01bd634 --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/libFFmpeg++.pro @@ -0,0 +1,9 @@ +TEMPLATE = lib +CONFIG += staticlib +CONFIG += c++1z +CONFIG -= debug_and_release + +SOURCES += $$files(*.cpp, true) +HEADERS += $$files(*.h, true) + +warning("Sources list " + $${SOURCES}) diff --git a/YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegLibrariesInterface.cpp b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegLibrariesInterface.cpp new file mode 100644 index 000000000..ccbc8f1fd --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegLibrariesInterface.cpp @@ -0,0 +1,293 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "FFmpegLibrariesInterface.h" + +namespace LibFFmpeg +{ + +namespace +{ + +using LoadingResult = tl::expected; +using LoadingResultAndLog = std::pair; + +std::vector getPossibleLibraryNames(std::string libraryName, int version) +{ + // The ffmpeg libraries are named using a major version number. E.g: avutil-55.dll on windows. + // On linux, the libraries may be named differently. On Ubuntu they are named + // libavutil-ffmpeg.so.55. On arch linux the name is libavutil.so.55. We will try to look for both + // namings. On MAC os (installed with homebrew), there is a link to the lib named + // libavutil.54.dylib. + +#if defined(_WIN32) + return {{libraryName + "-" + std::to_string(version)}}; +#elif defined(__APPLE__) + return {{"lib" + libraryName + "." + std::to_string(version) + ".dylib"}}; +#else + return {{"lib" + libraryName + "-ffmpeg.so." + std::to_string(version)}, + {"lib" + libraryName + ".so." + std::to_string(version)}}; +#endif + + return {}; +} + +bool tryLoadLibraryInPath(SharedLibraryLoader & lib, + const std::filesystem::path &absoluteDirectoryPath, + std::string libName, + const Version & version, + Log & log) +{ + log.push_back("Trying to load library " + libName + " in path " + absoluteDirectoryPath.string()); + + for (const auto &possibleLibName : getPossibleLibraryNames(libName, version.major)) + { + const auto filePath = absoluteDirectoryPath / possibleLibName; + const auto fileStatus = std::filesystem::status(filePath); + + if (fileStatus.type() == std::filesystem::file_type::not_found) + { + log.push_back("Loading using lib name " + possibleLibName + " failed. Can not find file " + + filePath.string()); + continue; + } + + const auto success = lib.load(filePath); + log.push_back("Loading library " + filePath.string() + (success ? " succeded" : " failed")); + if (success) + return true; + } + return false; +}; + +bool checkLibraryVersion(const std::string &libName, + unsigned ffmpegVersionOfLoadedLibrary, + const Version & expectedVersion, + Log & log) +{ + const auto loadedVersion = Version::fromFFmpegVersion(ffmpegVersionOfLoadedLibrary); + if (loadedVersion != expectedVersion) + { + log.push_back("Version of loaded " + libName + " library (" + to_string(loadedVersion) + + ") is not the one we are trying to load (" + to_string(expectedVersion) + ")"); + return false; + } + + log.push_back("Version check for library " + libName + " successfull. Version " + + to_string(loadedVersion) + "."); + return true; +} + +// These FFmpeg versions are supported. The numbers indicate the major version of +// the following libraries in this order: Util, codec, format, swresample +// The versions are sorted from newest to oldest, so that we try to open the newest ones first. +auto SupportedMajorLibraryVersionCombinations = { + LibraryVersions({Version(58), Version(60), Version(60), Version(4)}), + LibraryVersions({Version(57), Version(59), Version(59), Version(4)}), + LibraryVersions({Version(56), Version(58), Version(58), Version(3)}), + LibraryVersions({Version(55), Version(57), Version(57), Version(2)}), + LibraryVersions({Version(54), Version(56), Version(56), Version(1)}), +}; + +} // namespace + +FFmpegLibrariesInterface::LoadingResultAndLog +FFmpegLibrariesInterface::tryLoadFFmpegLibrariesInPath(const std::filesystem::path &path) +{ + Log log; + + std::filesystem::path absoluteDirectoryPath; + if (!path.empty()) + { + if (!std::filesystem::exists(path)) + { + log.push_back("The given path (" + path.string() + ") could not be found"); + return {false, log}; + } + + absoluteDirectoryPath = std::filesystem::absolute(path); + log.push_back("Using absolute path " + absoluteDirectoryPath.string()); + } + + for (const auto &libraryVersions : SupportedMajorLibraryVersionCombinations) + { + this->unloadAllLibraries(); + log.push_back("Unload libraries"); + + if (this->tryLoadLibrariesBindFunctionsAndCheckVersions(path, libraryVersions, log)) + { + log.push_back( + "Loading of ffmpeg libraries successfully finished. FFmpeg is ready to be used."); + return {false, log}; + } + } + + this->unloadAllLibraries(); + log.push_back("Unload libraries"); + log.push_back( + "We tried all supported versions in given path. Loading of ffmpeg libraries in path failed."); + + return {true, log}; +} + +bool FFmpegLibrariesInterface::tryLoadLibrariesBindFunctionsAndCheckVersions( + const std::filesystem::path &absoluteDirectoryPath, + const LibraryVersions & libraryVersions, + Log & log) +{ + // AVUtil + + if (!tryLoadLibraryInPath( + this->libAvutil, absoluteDirectoryPath, "avutil", libraryVersions.avutil, log)) + return false; + + if (const auto functions = functions::tryBindAVUtilFunctionsFromLibrary(this->libAvutil, log)) + this->avutil = functions.value(); + else + return false; + + if (!checkLibraryVersion("avUtil", this->avutil.avutil_version(), libraryVersions.avutil, log)) + return false; + + // SWResample + + if (!tryLoadLibraryInPath(this->libSwresample, + absoluteDirectoryPath, + "swresample", + libraryVersions.swresample, + log)) + return false; + + if (const auto functions = + functions::tryBindSwResampleFunctionsFromLibrary(this->libSwresample, log)) + this->swresample = functions.value(); + else + return false; + + if (!checkLibraryVersion( + "swresample", this->swresample.swresample_version(), libraryVersions.swresample, log)) + return false; + + // AVCodec + + if (!tryLoadLibraryInPath( + this->libAvcodec, absoluteDirectoryPath, "avcodec", libraryVersions.avcodec, log)) + return false; + + if (const auto functions = functions::tryBindAVCodecFunctionsFromLibrary(this->libAvcodec, log)) + this->avcodec = functions.value(); + else + return false; + + if (!checkLibraryVersion( + "avcodec", this->avcodec.avcodec_version(), libraryVersions.avcodec, log)) + return false; + + // AVFormat + + if (!tryLoadLibraryInPath( + this->libAvformat, absoluteDirectoryPath, "avformat", libraryVersions.avformat, log)) + return false; + + if (const auto functions = functions::tryBindAVFormatFunctionsFromLibrary(this->libAvformat, log)) + this->avformat = functions.value(); + else + return false; + + if (!checkLibraryVersion( + "avformat", this->avformat.avformat_version(), libraryVersions.avformat, log)) + return false; + + // Success + + this->libraryVersions.avutil = Version::fromFFmpegVersion(this->avutil.avutil_version()); + this->libraryVersions.avcodec = Version::fromFFmpegVersion(this->avcodec.avcodec_version()); + this->libraryVersions.avformat = Version::fromFFmpegVersion(this->avformat.avformat_version()); + this->libraryVersions.swresample = + Version::fromFFmpegVersion(this->swresample.swresample_version()); + + this->avutil.av_log_set_callback(&FFmpegLibrariesInterface::avLogCallback); + + if (this->libraryVersions.avformat.major < 59) + this->avformat.av_register_all(); + + return true; +} + +void FFmpegLibrariesInterface::unloadAllLibraries() +{ + this->libAvutil.unload(); + this->libSwresample.unload(); + this->libAvcodec.unload(); + this->libAvformat.unload(); +} + +std::vector FFmpegLibrariesInterface::getLibrariesInfo() const +{ + if (!this->libAvutil || !this->libSwresample || !this->libAvcodec || !this->libAvformat) + return {}; + + std::vector infoPerLIbrary; + + auto addLibraryInfo = [&infoPerLIbrary](const char * name, + const std::filesystem::path &path, + const unsigned ffmpegVersion) { + const auto libraryVersion = Version::fromFFmpegVersion(ffmpegVersion); + const auto version = to_string(libraryVersion); + + infoPerLIbrary.push_back(LibraryInfo({name, path, version})); + }; + + addLibraryInfo("AVFormat", this->libAvformat.getLibraryPath(), this->avformat.avformat_version()); + addLibraryInfo("AVCodec", this->libAvcodec.getLibraryPath(), this->avcodec.avcodec_version()); + addLibraryInfo("AVUtil", this->libAvutil.getLibraryPath(), this->avutil.avutil_version()); + addLibraryInfo( + "SwResample", this->libSwresample.getLibraryPath(), this->swresample.swresample_version()); + + return infoPerLIbrary; +} + +std::string FFmpegLibrariesInterface::logListFFmpeg; + +void FFmpegLibrariesInterface::avLogCallback(void *, int level, const char *fmt, va_list vargs) +{ + std::string message; + va_list vargs_copy; + va_copy(vargs_copy, vargs); + size_t len = vsnprintf(0, 0, fmt, vargs_copy); + message.resize(len); + vsnprintf(&message[0], len + 1, fmt, vargs); + + FFmpegLibrariesInterface::logListFFmpeg.append("Level " + std::to_string(level) + message); +} + +} // namespace LibFFmpeg diff --git a/YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegLibrariesInterface.h b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegLibrariesInterface.h new file mode 100644 index 000000000..b89ca80e3 --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegLibrariesInterface.h @@ -0,0 +1,92 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace LibFFmpeg +{ + +struct LibraryInfo +{ + std::string name; + std::filesystem::path path; + std::string version; +}; + +class FFmpegLibrariesInterface +{ +public: + FFmpegLibrariesInterface() = default; + ~FFmpegLibrariesInterface() = default; + + using LoadingResultAndLog = std::pair; + LoadingResultAndLog tryLoadFFmpegLibrariesInPath(const std::filesystem::path &path); + + std::vector getLibrariesInfo() const; + + functions::AvFormatFunctions avformat{}; + functions::AvCodecFunctions avcodec{}; + functions::AvUtilFunctions avutil{}; + functions::SwResampleFunctions swresample{}; + +private: + bool + tryLoadLibrariesBindFunctionsAndCheckVersions(const std::filesystem::path &absoluteDirectoryPath, + const LibraryVersions & libraryVersions, + Log & log); + + void unloadAllLibraries(); + + SharedLibraryLoader libAvutil; + SharedLibraryLoader libSwresample; + SharedLibraryLoader libAvcodec; + SharedLibraryLoader libAvformat; + + LibraryVersions libraryVersions{}; + + static std::string logListFFmpeg; + static void avLogCallback(void *ptr, int level, const char *fmt, va_list vargs); + + friend class FFmpegLibrariesInterfaceBuilder; +}; + +} // namespace LibFFmpeg diff --git a/YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegLibrariesInterfaceBuilder.cpp b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegLibrariesInterfaceBuilder.cpp new file mode 100644 index 000000000..0718243a5 --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegLibrariesInterfaceBuilder.cpp @@ -0,0 +1,93 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "FFmpegLibrariesInterfaceBuilder.h" + +namespace LibFFmpeg +{ + +LibrariesLoadingResult FFmpegLibrariesInterfaceBuilder::tryLoadingOfLibraries() +{ + LibrariesLoadingResult result; + + if (this->forceReload) + result.loadingLog.push_back("Library reload forced. Will skip cache check."); + else + { + if (auto cachedLibrariesInterface = this->lastLoadedLibraries.lock()) + { + result.loadingLog.push_back("Cached libraries still loaded. Returning cached libraries."); + result.librariesInterface = cachedLibrariesInterface; + return result; + } + } + + if (this->searchPaths.empty()) + { + result.loadingLog.push_back( + "No search paths specified. We will only try the default empty path."); + this->searchPaths.push_back(""); + } + + auto libraryInterface = std::make_shared(); + + for (const auto &path : this->searchPaths) + { + result.loadingLog.push_back("Trying to load the libraries in the path " + path.string()); + + const auto [success, log] = libraryInterface->tryLoadFFmpegLibrariesInPath(path); + result.loadingLog.insert(result.loadingLog.begin(), log.begin(), log.end()); + + if (success) + { + result.librariesInterface = libraryInterface; + return result; + } + } + + return result; +} + +FFmpegLibrariesInterfaceBuilder &FFmpegLibrariesInterfaceBuilder::withAdditionalSearchPaths( + const std::vector &additionalPath) +{ + this->searchPaths.insert(this->searchPaths.begin(), additionalPath.begin(), additionalPath.end()); + return *this; +} + +FFmpegLibrariesInterfaceBuilder &FFmpegLibrariesInterfaceBuilder::withForcedReload() +{ + this->forceReload = true; + return *this; +} + +} // namespace LibFFmpeg \ No newline at end of file diff --git a/YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegLibrariesInterfaceBuilder.h b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegLibrariesInterfaceBuilder.h new file mode 100644 index 000000000..40a1c045b --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegLibrariesInterfaceBuilder.h @@ -0,0 +1,68 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +#include + +namespace LibFFmpeg +{ + +struct LibrariesLoadingResult +{ + std::shared_ptr librariesInterface{}; + std::string errorMessage{}; + std::vector loadingLog{}; + + explicit operator bool() const { return this->librariesInterface.get() != nullptr; }; +}; + +class FFmpegLibrariesInterfaceBuilder +{ +public: + FFmpegLibrariesInterfaceBuilder() = default; + + LibrariesLoadingResult tryLoadingOfLibraries(); + + FFmpegLibrariesInterfaceBuilder & + withAdditionalSearchPaths(const std::vector &additionalPath); + FFmpegLibrariesInterfaceBuilder &withForcedReload(); + +private: + std::vector searchPaths{}; + bool forceReload{false}; + std::weak_ptr lastLoadedLibraries{}; +}; + +} // namespace LibFFmpeg diff --git a/YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegVersionHandler.cpp b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegVersionHandler.cpp new file mode 100644 index 000000000..40e6be3ca --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegVersionHandler.cpp @@ -0,0 +1,426 @@ +// /* This file is part of YUView - The YUV player with advanced analytics toolset +// * +// * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY +// * +// * This program is free software; you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation; either version 3 of the License, or +// * (at your option) any later version. +// * +// * In addition, as a special exception, the copyright holders give +// * permission to link the code of portions of this program with the +// * OpenSSL library under certain conditions as described in each +// * individual source file, and distribute linked combinations including +// * the two. +// * +// * You must obey the GNU General Public License in all respects for all +// * of the code used other than OpenSSL. If you modify file(s) with this +// * exception, you may extend this exception to your version of the +// * file(s), but you are not obligated to do so. If you do not wish to do +// * so, delete this exception statement from your version. If you delete +// * this exception statement from all source files in the program, then +// * also delete it here. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see . +// */ + +// #include "FFmpegVersionHandler.h" +// #include +// #include +// #include + +// namespace LibFFmpeg +// { + +// namespace +// { + +// LibraryVersions getLibraryVersionsFromLoadedLibraries(const FFmpegLibraryFunctions &libraries) +// { +// const auto avFormatVersion = Version::fromFFmpegVersion(libraries.avformat.avformat_version()); +// const auto avCodecVersion = Version::fromFFmpegVersion(libraries.avcodec.avcodec_version()); +// const auto avUtilVersion = Version::fromFFmpegVersion(libraries.avutil.avutil_version()); +// const auto swresampleVersion = +// Version::fromFFmpegVersion(libraries.swresample.swresample_version()); + +// return {avFormatVersion, avCodecVersion, avUtilVersion, swresampleVersion}; +// } + +// tl::expected +// checkMajorVersionWithLibraries(const LibraryVersions &librariesInfo, +// const LibraryVersions &expectedMajorVersion) +// { +// auto createErrorString = [](std::string_view libname, +// const Version & realVersion, +// const Version & expectedVersion) -> std::string { +// std::ostringstream stream; +// stream << "The openend " << libname << " returned a different version (" << realVersion +// << ") than we are looking for (" << expectedVersion << ")."; +// return stream.str(); +// }; + +// if (expectedMajorVersion.avcodec != librariesInfo.avcodec) +// return tl::unexpected( +// createErrorString("avcodec", librariesInfo.avcodec, expectedMajorVersion.avcodec)); + +// if (expectedMajorVersion.avformat != librariesInfo.avformat) +// return tl::unexpected( +// createErrorString("avformat", librariesInfo.avformat, expectedMajorVersion.avformat)); + +// if (expectedMajorVersion.avutil != librariesInfo.avutil) +// return tl::unexpected( +// createErrorString("avutil", librariesInfo.avutil, expectedMajorVersion.avutil)); + +// if (expectedMajorVersion.swresample != librariesInfo.swresample) +// return tl::unexpected( +// createErrorString("swresample", librariesInfo.swresample, expectedMajorVersion.swresample)); + +// return {}; +// } + +// } // namespace + +// AVCodecIDWrapper FFmpegVersionHandler::getCodecIDWrapper(AVCodecID id) +// { +// const auto codecName = std::string(lib.avcodec.avcodec_get_name(id)); +// return AVCodecIDWrapper(id, codecName); +// } + +// AVCodecID FFmpegVersionHandler::getCodecIDFromWrapper(AVCodecIDWrapper &wrapper) +// { +// if (wrapper.getCodecID() != AV_CODEC_ID_NONE) +// return wrapper.getCodecID(); + +// int codecID = 1; +// std::string codecName; +// do +// { +// codecName = std::string(this->lib.avcodec.avcodec_get_name(AVCodecID(codecID))); +// if (codecName == wrapper.getCodecName()) +// { +// wrapper.setCodecID(AVCodecID(codecID)); +// return wrapper.getCodecID(); +// } +// codecID++; +// } while (codecName != "unknown_codec"); + +// return AV_CODEC_ID_NONE; +// } + +// bool FFmpegVersionHandler::configureDecoder(AVCodecContextWrapper & decCtx, +// AVCodecParametersWrapper &codecpar) +// { +// if (this->lib.avcodec.newParametersAPIAvailable) +// { +// // Use the new avcodec_parameters_to_context function. +// auto origin_par = codecpar.getCodecParameters(); +// if (!origin_par) +// return false; +// auto ret = this->lib.avcodec.avcodec_parameters_to_context(decCtx.getCodec(), origin_par); +// if (ret < 0) +// return false; +// } +// else +// { +// // TODO: Is this even necessary / what is really happening here? + +// // The new parameters API is not available. Perform what the function would do. +// // This is equal to the implementation of avcodec_parameters_to_context. +// // AVCodecContext *ctxSrc = videoStream.getCodec().getCodec(); +// // int ret = lib.AVCodecContextCopyParameters(ctxSrc, decCtx.getCodec()); +// // return setOpeningError(QStringLiteral("Could not copy decoder parameters from stream +// // decoder.")); +// } +// return true; +// } + +// int FFmpegVersionHandler::pushPacketToDecoder(AVCodecContextWrapper &decCtx, AVPacketWrapper &pkt) +// { +// if (!pkt) +// return this->lib.avcodec.avcodec_send_packet(decCtx.getCodec(), nullptr); +// else +// return this->lib.avcodec.avcodec_send_packet(decCtx.getCodec(), pkt.getPacket()); +// } + +// int FFmpegVersionHandler::getFrameFromDecoder(AVCodecContextWrapper &decCtx, AVFrameWrapper &frame) +// { +// return this->lib.avcodec.avcodec_receive_frame(decCtx.getCodec(), frame.getFrame()); +// } + +// void FFmpegVersionHandler::flush_buffers(AVCodecContextWrapper &decCtx) +// { +// lib.avcodec.avcodec_flush_buffers(decCtx.getCodec()); +// } + + + +// FFmpegVersionHandler::FFmpegVersionHandler() +// { +// this->librariesLoaded = false; +// } + +// FFmpegVersionHandler::~FFmpegVersionHandler() +// { +// } + + + +// LibraryLoadingResult +// FFmpegVersionHandler::loadFFmpegLibraries(std::vector searchPaths) +// { +// LibraryLoadingResult result; + +// if (this->librariesLoaded) +// { +// result.addLogLine("Libraries already loaded"); +// return result; +// } + +// for (const auto &path : searchPaths) +// { +// result.addLogLine("Trying to load the libraries in the path " + path.string()); + +// auto resultForPath = this->loadFFmpegLibraryInPath(path); +// result.loadingLog.append(resultForPath.loadingLog); +// this->librariesLoaded = resultForPath.success; +// if (resultForPath.success) +// { +// result.success = true; +// break; +// } +// } + +// if (this->librariesLoaded) +// this->lib.avutil.av_log_set_callback(&FFmpegVersionHandler::avLogCallback); + +// return result; +// } + +// bool FFmpegVersionHandler::openInput(AVFormatContextWrapper &fmt, QString url) +// { +// AVFormatContext *f_ctx = nullptr; +// int ret = +// this->lib.avformat.avformat_open_input(&f_ctx, url.toStdString().c_str(), nullptr, nullptr); +// if (ret < 0) +// return false; +// if (f_ctx == nullptr) +// return false; + +// // The wrapper will take ownership of this pointer +// fmt = AVFormatContextWrapper(f_ctx, this->libraryVersions); + +// ret = lib.avformat.avformat_find_stream_info(fmt.getFormatCtx(), nullptr); +// if (ret < 0) +// return false; + +// return true; +// } + +// AVCodecParametersWrapper FFmpegVersionHandler::allocCodecParameters() +// { +// return AVCodecParametersWrapper(this->lib.avcodec.avcodec_parameters_alloc(), +// this->libraryVersions); +// } + +// AVCodecWrapper FFmpegVersionHandler::findDecoder(AVCodecIDWrapper codecId) +// { +// AVCodecID avCodecID = getCodecIDFromWrapper(codecId); +// AVCodec * c = this->lib.avcodec.avcodec_find_decoder(avCodecID); +// if (c == nullptr) +// return {}; +// return AVCodecWrapper(c, this->libraryVersions); +// } + +// AVCodecContextWrapper FFmpegVersionHandler::allocDecoder(AVCodecWrapper &codec) +// { +// return AVCodecContextWrapper(this->lib.avcodec.avcodec_alloc_context3(codec.getAVCodec()), +// this->libraryVersions); +// } + +// int FFmpegVersionHandler::dictSet(AVDictionaryWrapper &dict, +// const char * key, +// const char * value, +// int flags) +// { +// AVDictionary *d = dict.getDictionary(); +// int ret = this->lib.avutil.av_dict_set(&d, key, value, flags); +// dict.setDictionary(d); +// return ret; +// } + +// StringPairVec +// FFmpegVersionHandler::getDictionaryEntries(AVDictionaryWrapper d, QString key, int flags) +// { +// StringPairVec ret; +// AVDictionaryEntry *tag = NULL; +// while ((tag = this->lib.avutil.av_dict_get(d.getDictionary(), key.toLatin1().data(), tag, flags))) +// { +// StringPair pair; +// pair.first = std::string(tag->key); +// pair.second = std::string(tag->value); +// ret.push_back(pair); +// } +// return ret; +// } +// int FFmpegVersionHandler::avcodecOpen2(AVCodecContextWrapper &decCtx, +// AVCodecWrapper & codec, +// AVDictionaryWrapper & dict) +// { +// auto d = dict.getDictionary(); +// int ret = this->lib.avcodec.avcodec_open2(decCtx.getCodec(), codec.getAVCodec(), &d); +// dict.setDictionary(d); +// return ret; +// } + +// AVFrameSideDataWrapper FFmpegVersionHandler::getSideData(AVFrameWrapper & frame, +// AVFrameSideDataType type) +// { +// auto sd = this->lib.avutil.av_frame_get_side_data(frame.getFrame(), type); +// return AVFrameSideDataWrapper(sd, this->libraryVersions); +// } + +// AVDictionaryWrapper FFmpegVersionHandler::getMetadata(AVFrameWrapper &frame) +// { +// AVDictionary *dict; +// if (this->libraryVersions.avutil.major < 57) +// dict = this->lib.avutil.av_frame_get_metadata(frame.getFrame()); +// else +// dict = frame.getMetadata(); +// return AVDictionaryWrapper(dict); +// } + +// int FFmpegVersionHandler::seekFrame(AVFormatContextWrapper &fmt, int stream_idx, int64_t dts) +// { +// int ret = +// this->lib.avformat.av_seek_frame(fmt.getFormatCtx(), stream_idx, dts, AVSEEK_FLAG_BACKWARD); +// return ret; +// } + +// int FFmpegVersionHandler::seekBeginning(AVFormatContextWrapper &fmt) +// { +// // This is "borrowed" from the ffmpeg sources +// // (https://ffmpeg.org/doxygen/4.0/ffmpeg_8c_source.html seek_to_start) +// return lib.avformat.av_seek_frame(fmt.getFormatCtx(), -1, fmt.getStartTime(), 0); +// } + +// LibraryLoadingResult FFmpegVersionHandler::loadFFmpegLibraryInPath(const std::filesystem::path path) +// { +// LibraryLoadingResult result; +// for (auto version : SupportedMajorLibraryVersionCombinations) +// { +// if (auto loadResult = this->lib.loadFFmpegLibraryInPath(path, version)) +// { +// result.loadingLog.append(loadResult.loadingLog); + +// result.addLogLine("Checking versions avutil " + to_string(version.avutil) + ", swresample " + +// to_string(version.swresample) + ", avcodec " + to_string(version.avcodec) + +// ", avformat " + to_string(version.avformat)); + +// const auto libraryVersions = getLibraryVersionsFromLoadedLibraries(this->lib); + +// const auto checkVersionResult = checkMajorVersionWithLibraries(libraryVersions, version); +// if (checkVersionResult.has_value()) +// { +// this->libraryVersions = libraryVersions; + +// if (this->libraryVersions.avformat.major < 59) +// this->lib.avformat.av_register_all(); + +// result.success = true; +// result.addLogLine("Library version check passed."); +// return result; +// } +// else +// { +// result.addLogLine(checkVersionResult.error()); +// } +// } +// } + +// result.errorMessage = "No supported ffmpeg library files found in path " + path.string(); +// return result; +// } + +// LibraryLoadingResult +// FFmpegVersionHandler::checkPathForUsableFFmpeg(const std::filesystem::path &path) +// { +// FFmpegVersionHandler handler; +// return handler.loadFFmpegLibraryInPath(path); +// } + +// void FFmpegVersionHandler::enableLoggingWarning() +// { +// lib.avutil.av_log_set_level(AV_LOG_WARNING); +// } + +// AVPixFmtDescriptorWrapper +// FFmpegVersionHandler::getAvPixFmtDescriptionFromAvPixelFormat(AVPixelFormat pixFmt) +// { +// if (pixFmt == AV_PIX_FMT_NONE) +// return {}; +// return AVPixFmtDescriptorWrapper(lib.avutil.av_pix_fmt_desc_get(pixFmt), this->libraryVersions); +// } + +// AVPixelFormat +// FFmpegVersionHandler::getAVPixelFormatFromPixelFormatYUV(video::yuv::PixelFormatYUV pixFmt) +// { +// AVPixFmtDescriptorWrapper wrapper; +// wrapper.setValuesFromPixelFormatYUV(pixFmt); + +// // We will have to search through all pixel formats which the library knows and compare them to +// // the one we are looking for. Unfortunately there is no other more direct search function in +// // libavutil. +// auto desc = this->lib.avutil.av_pix_fmt_desc_next(nullptr); +// while (desc != nullptr) +// { +// AVPixFmtDescriptorWrapper descWrapper(desc, this->libraryVersions); + +// if (descWrapper == wrapper) +// return this->lib.avutil.av_pix_fmt_desc_get_id(desc); + +// // Get the next descriptor +// desc = this->lib.avutil.av_pix_fmt_desc_next(desc); +// } + +// return AV_PIX_FMT_NONE; +// } + +// AVFrameWrapper FFmpegVersionHandler::allocateFrame() +// { +// auto framePtr = this->lib.avutil.av_frame_alloc(); +// return AVFrameWrapper(framePtr, this->libraryVersions); +// } + +// void FFmpegVersionHandler::freeFrame(AVFrameWrapper &frame) +// { +// auto framePtr = frame.getFrame(); +// this->lib.avutil.av_frame_free(&framePtr); +// frame.clear(); +// } + +// AVPacketWrapper FFmpegVersionHandler::allocatePacket() +// { +// auto rawPacket = this->lib.avcodec.av_packet_alloc(); +// this->lib.avcodec.av_init_packet(rawPacket); +// return AVPacketWrapper(rawPacket, this->libraryVersions); +// } + +// void FFmpegVersionHandler::unrefPacket(AVPacketWrapper &packet) +// { +// this->lib.avcodec.av_packet_unref(packet.getPacket()); +// } + +// void FFmpegVersionHandler::freePacket(AVPacketWrapper &packet) +// { +// auto packetPtr = packet.getPacket(); +// this->lib.avcodec.av_packet_free(&packetPtr); +// packet.clear(); +// } + +// } // namespace LibFFmpeg diff --git a/YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegVersionHandler.h b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegVersionHandler.h new file mode 100644 index 000000000..94c1eb218 --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/FFmpegVersionHandler.h @@ -0,0 +1,132 @@ +// /* This file is part of YUView - The YUV player with advanced analytics toolset +// * +// * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY +// * +// * This program is free software; you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation; either version 3 of the License, or +// * (at your option) any later version. +// * +// * In addition, as a special exception, the copyright holders give +// * permission to link the code of portions of this program with the +// * OpenSSL library under certain conditions as described in each +// * individual source file, and distribute linked combinations including +// * the two. +// * +// * You must obey the GNU General Public License in all respects for all +// * of the code used other than OpenSSL. If you modify file(s) with this +// * exception, you may extend this exception to your version of the +// * file(s), but you are not obligated to do so. If you do not wish to do +// * so, delete this exception statement from your version. If you delete +// * this exception statement from all source files in the program, then +// * also delete it here. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see . +// */ + +// #pragma once + +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include + +// namespace LibFFmpeg +// { + +// class FFmpegVersionHandler +// { +// public: +// FFmpegVersionHandler(); +// ~FFmpegVersionHandler(); + +// // Try to load the ffmpeg libraries and get all the function pointers. +// LibraryLoadingResult loadFFmpegLibraries(std::vector searchPaths); + +// std::vector getLibrariesInfo() const { return this->lib.getLibrariesInfo(); } + +// // Only these functions can be used to get valid versions of these wrappers (they have to use +// // ffmpeg functions to retrieve the needed information) +// AVCodecIDWrapper getCodecIDWrapper(AVCodecID id); +// AVCodecID getCodecIDFromWrapper(AVCodecIDWrapper &wrapper); +// AVPixFmtDescriptorWrapper getAvPixFmtDescriptionFromAvPixelFormat(AVPixelFormat pixFmt); +// AVPixelFormat getAVPixelFormatFromPixelFormatYUV(video::yuv::PixelFormatYUV pixFmt); + +// AVFrameWrapper allocateFrame(); +// void freeFrame(AVFrameWrapper &frame); +// AVPacketWrapper allocatePacket(); +// void unrefPacket(AVPacketWrapper &packet); +// void freePacket(AVPacketWrapper &packet); + +// bool configureDecoder(AVCodecContextWrapper &decCtx, AVCodecParametersWrapper &codecpar); + +// // Push a packet to the given decoder using avcodec_send_packet +// int pushPacketToDecoder(AVCodecContextWrapper &decCtx, AVPacketWrapper &pkt); +// // Retrive a frame using avcodec_receive_frame +// int getFrameFromDecoder(AVCodecContextWrapper &decCtx, AVFrameWrapper &frame); + +// void flush_buffers(AVCodecContextWrapper &decCtx); + +// LibraryVersions libVersions; + +// // Open the input file. This will call avformat_open_input and avformat_find_stream_info. +// bool openInput(AVFormatContextWrapper &fmt, QString url); +// // Try to find a decoder for the given codecID +// AVCodecWrapper findDecoder(AVCodecIDWrapper codecID); +// // Allocate the decoder (avcodec_alloc_context3) +// AVCodecContextWrapper allocDecoder(AVCodecWrapper &codec); +// // Set info in the dictionary +// int dictSet(AVDictionaryWrapper &dict, const char *key, const char *value, int flags); +// // Get all entries with the given key (leave empty for all) +// StringPairVec getDictionaryEntries(AVDictionaryWrapper d, QString key, int flags); +// // Allocate a new set of codec parameters +// AVCodecParametersWrapper allocCodecParameters(); + +// // Open the codec +// int avcodecOpen2(AVCodecContextWrapper &decCtx, AVCodecWrapper &codec, AVDictionaryWrapper &dict); +// // Get side/meta data +// AVFrameSideDataWrapper getSideData(AVFrameWrapper &frame, AVFrameSideDataType type); +// AVDictionaryWrapper getMetadata(AVFrameWrapper &frame); + +// // Seek to a specific frame +// int seekFrame(AVFormatContextWrapper &fmt, int stream_idx, int64_t dts); +// int seekBeginning(AVFormatContextWrapper &fmt); + +// // All the function pointers of the ffmpeg library +// FFmpegLibraryFunctions lib; + +// static AVPixelFormat convertYUVAVPixelFormat(video::yuv::PixelFormatYUV fmt); + +// static LibraryLoadingResult checkPathForUsableFFmpeg(const std::filesystem::path &path); + +// // Logging. By default we set the logging level of ffmpeg to AV_LOG_ERROR (Log errors and +// // everything worse) +// static QStringList getFFmpegLog() { return logListFFmpeg; } +// void enableLoggingWarning(); + +// private: +// LibraryLoadingResult loadFFmpegLibraryInPath(const std::filesystem::path); + +// bool librariesLoaded{}; +// LibraryVersions libraryVersions{}; + +// // FFmpeg has a callback where it loggs stuff. This log goes here. +// static QStringList logListFFmpeg; +// static void avLogCallback(void *ptr, int level, const char *fmt, va_list vargs); +// }; + +// } // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/LibraryLoader.cpp b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/SharedLibraryLoader.cpp similarity index 89% rename from YUViewLib/src/ffmpeg/LibraryLoader.cpp rename to YUViewLib/externalLibs/LibFFmpeg++/libHandling/SharedLibraryLoader.cpp index be0496cda..8a8741001 100644 --- a/YUViewLib/src/ffmpeg/LibraryLoader.cpp +++ b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/SharedLibraryLoader.cpp @@ -30,18 +30,18 @@ * along with this program. If not, see . */ -#include "LibraryLoader.h" +#include "SharedLibraryLoader.h" -namespace FFmpeg +namespace LibFFmpeg { -void LibraryLoader::unload() +void SharedLibraryLoader::unload() { this->library.unload(); this->libraryPath.clear(); }; -bool LibraryLoader::load(std::filesystem::path pathToLib) +bool SharedLibraryLoader::load(std::filesystem::path pathToLib) { const auto filePathQString = QString::fromStdString(pathToLib.string()); this->library.setFileName(filePathQString); @@ -51,10 +51,10 @@ bool LibraryLoader::load(std::filesystem::path pathToLib) return success; }; -FunctionPointer LibraryLoader::resolve(std::string functionName) +FunctionPointer SharedLibraryLoader::resolve(std::string functionName) { auto functionPointer = this->library.resolve(functionName.c_str()); return functionPointer; }; -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/LibraryLoader.h b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/SharedLibraryLoader.h similarity index 85% rename from YUViewLib/src/ffmpeg/LibraryLoader.h rename to YUViewLib/externalLibs/LibFFmpeg++/libHandling/SharedLibraryLoader.h index 8e60318ff..085646653 100644 --- a/YUViewLib/src/ffmpeg/LibraryLoader.h +++ b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/SharedLibraryLoader.h @@ -37,13 +37,13 @@ typedef void (*FunctionPointer)(); -namespace FFmpeg +namespace LibFFmpeg { -class LibraryLoader +class SharedLibraryLoader { public: - LibraryLoader(/* args */) = default; + SharedLibraryLoader() = default; void unload(); bool load(std::filesystem::path pathToLib); @@ -53,10 +53,18 @@ class LibraryLoader operator bool() const { return this->library.isLoaded(); } + template + void tryResolveFunction(std::function &function, const char *symbolName) const + { + if (auto ptr = this->library.resolve(symbolName)) + function = reinterpret_cast(ptr); + } + private: + // Todo: Replace this with alternative QLibrary library; std::filesystem::path libraryPath; }; -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AVFormatFunctions.cpp b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AVFormatFunctions.cpp new file mode 100644 index 000000000..301b280f7 --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AVFormatFunctions.cpp @@ -0,0 +1,97 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "AVFormatFunctions.h" + +#include "Functions.h" + +namespace LibFFmpeg::functions +{ + +std::optional tryBindFunctionsFromLibrary(SharedLibraryLoader &lib, Log &log) +{ + if (!lib) + { + log.push_back("Binding of avFormat functions failed. Library is not loaded."); + return {}; + } + + AvFormatFunctions functions; + + lib.tryResolveFunction(functions.avformat_version, "avformat_version"); + lib.tryResolveFunction(functions.av_register_all, "av_register_all"); + lib.tryResolveFunction(functions.avformat_open_input, "avformat_open_input"); + lib.tryResolveFunction(functions.avformat_close_input, "avformat_close_input"); + lib.tryResolveFunction(functions.avformat_find_stream_info, "avformat_find_stream_info"); + lib.tryResolveFunction(functions.av_read_frame, "av_read_frame"); + lib.tryResolveFunction(functions.av_seek_frame, "av_seek_frame"); + + std::vector missingFunctions; + + checkForMissingFunctionAndLog( + functions.avformat_version, "avformat_version", missingFunctions, log); + + if (!functions.avformat_version) + { + log.push_back("Binding avFormat functions failed. Missing function avformat_version"); + return {}; + } + + const auto version = Version::fromFFmpegVersion(functions.avformat_version()); + + if (version.major < 59) + checkForMissingFunctionAndLog( + functions.av_register_all, "av_register_all", missingFunctions, log); + + checkForMissingFunctionAndLog( + functions.avformat_open_input, "avformat_open_input", missingFunctions, log); + checkForMissingFunctionAndLog( + functions.avformat_close_input, "avformat_close_input", missingFunctions, log); + checkForMissingFunctionAndLog( + functions.avformat_find_stream_info, "avformat_find_stream_info", missingFunctions, log); + checkForMissingFunctionAndLog(functions.av_read_frame, "av_read_frame", missingFunctions, log); + checkForMissingFunctionAndLog(functions.av_seek_frame, "av_seek_frame", missingFunctions, log); + checkForMissingFunctionAndLog( + functions.avformat_version, "avformat_version", missingFunctions, log); + + if (!missingFunctions.empty()) + { + log.push_back("Binding avFormat functions failed. Missing functions: " + + to_string(missingFunctions)); + return {}; + } + + log.push_back("Binding of avFormat functions successful."); + return functions; +} + +} // namespace LibFFmpeg::functions diff --git a/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AVFormatFunctions.h b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AVFormatFunctions.h new file mode 100644 index 000000000..bc9f74518 --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AVFormatFunctions.h @@ -0,0 +1,59 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include + +namespace LibFFmpeg::functions +{ + +struct AvFormatFunctions +{ + std::function av_register_all; + std::function + avformat_open_input; + std::function avformat_close_input; + std::function avformat_find_stream_info; + std::function av_read_frame; + std::function + av_seek_frame; + std::function avformat_version; +}; + +std::optional tryBindAVFormatFunctionsFromLibrary(SharedLibraryLoader &lib, + Log & log); + +} // namespace LibFFmpeg::functions diff --git a/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AvCodecFunctions.cpp b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AvCodecFunctions.cpp new file mode 100644 index 000000000..20cbdf8af --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AvCodecFunctions.cpp @@ -0,0 +1,127 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "AvCodecFunctions.h" + +#include "Functions.h" + +namespace LibFFmpeg::functions +{ + +std::optional tryBindAVCodecFunctionsFromLibrary(SharedLibraryLoader &lib, + Log & log) +{ + if (!lib) + { + log.push_back("Binding of avCodec functions failed. Library is not loaded."); + return {}; + } + + AvCodecFunctions functions; + + lib.tryResolveFunction(functions.avcodec_find_decoder, "avcodec_find_decoder"); + lib.tryResolveFunction(functions.avcodec_alloc_context3, "avcodec_alloc_context3"); + lib.tryResolveFunction(functions.avcodec_open2, "avcodec_open2"); + lib.tryResolveFunction(functions.avcodec_free_context, "avcodec_free_context"); + lib.tryResolveFunction(functions.av_packet_alloc, "av_packet_alloc"); + lib.tryResolveFunction(functions.av_packet_free, "av_packet_free"); + lib.tryResolveFunction(functions.av_init_packet, "av_init_packet"); + lib.tryResolveFunction(functions.av_packet_unref, "av_packet_unref"); + lib.tryResolveFunction(functions.avcodec_flush_buffers, "avcodec_flush_buffers"); + lib.tryResolveFunction(functions.avcodec_version, "avcodec_version"); + lib.tryResolveFunction(functions.avcodec_get_name, "avcodec_get_name"); + lib.tryResolveFunction(functions.avcodec_parameters_alloc, "avcodec_parameters_alloc"); + lib.tryResolveFunction(functions.avcodec_send_packet, "avcodec_send_packet"); + lib.tryResolveFunction(functions.avcodec_receive_frame, "avcodec_receive_frame"); + lib.tryResolveFunction(functions.avcodec_parameters_to_context, "avcodec_parameters_to_context"); + lib.tryResolveFunction(functions.avcodec_decode_video2, "avcodec_decode_video2"); + + std::vector missingFunctions; + + checkForMissingFunctionAndLog( + functions.avcodec_find_decoder, "avcodec_find_decoder", missingFunctions, log); + checkForMissingFunctionAndLog( + functions.avcodec_alloc_context3, "avcodec_alloc_context3", missingFunctions, log); + checkForMissingFunctionAndLog(functions.avcodec_open2, "avcodec_open2", missingFunctions, log); + checkForMissingFunctionAndLog( + functions.avcodec_free_context, "avcodec_free_context", missingFunctions, log); + checkForMissingFunctionAndLog( + functions.av_packet_alloc, "av_packet_alloc", missingFunctions, log); + checkForMissingFunctionAndLog(functions.av_packet_free, "av_packet_free", missingFunctions, log); + checkForMissingFunctionAndLog(functions.av_init_packet, "av_init_packet", missingFunctions, log); + checkForMissingFunctionAndLog( + functions.av_packet_unref, "av_packet_unref", missingFunctions, log); + checkForMissingFunctionAndLog( + functions.avcodec_flush_buffers, "avcodec_flush_buffers", missingFunctions, log); + checkForMissingFunctionAndLog( + functions.avcodec_version, "avcodec_version", missingFunctions, log); + checkForMissingFunctionAndLog( + functions.avcodec_get_name, "avcodec_get_name", missingFunctions, log); + checkForMissingFunctionAndLog( + functions.avcodec_parameters_alloc, "avcodec_parameters_alloc", missingFunctions, log); + + std::vector missingFunctionsNewApi; + + checkForMissingFunctionAndLog( + functions.avcodec_send_packet, "avcodec_send_packet", missingFunctionsNewApi, log); + checkForMissingFunctionAndLog( + functions.avcodec_receive_frame, "avcodec_receive_frame", missingFunctionsNewApi, log); + checkForMissingFunctionAndLog(functions.avcodec_parameters_to_context, + "avcodec_parameters_to_context", + missingFunctionsNewApi, + log); + + if (missingFunctionsNewApi.empty()) + { + log.push_back("New Decoding API found. Skipping check for old API function."); + functions.newParametersAPIAvailable = true; + } + else + { + log.push_back("New Decoding API not found. Missing functions " + + to_string(missingFunctionsNewApi) + ". Checking old decoding API."); + checkForMissingFunctionAndLog( + functions.avcodec_decode_video2, "avcodec_decode_video2", missingFunctions, log); + } + + if (!missingFunctions.empty()) + { + log.push_back("Binding avCodec functions failed. Missing functions: " + + to_string(missingFunctions)); + return {}; + } + + log.push_back("Binding of avCodec functions successful."); + return functions; +} + +} // namespace LibFFmpeg::functions diff --git a/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AvCodecFunctions.h b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AvCodecFunctions.h new file mode 100644 index 000000000..e6c5b123b --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AvCodecFunctions.h @@ -0,0 +1,71 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include + +namespace LibFFmpeg::functions +{ + +struct AvCodecFunctions +{ + std::function avcodec_find_decoder; + std::function avcodec_alloc_context3; + std::function + avcodec_open2; + std::function avcodec_free_context; + std::function av_packet_alloc; + std::function av_packet_free; + std::function av_init_packet; + std::function av_packet_unref; + std::function avcodec_flush_buffers; + std::function avcodec_version; + std::function avcodec_get_name; + std::function avcodec_parameters_alloc; + // The following functions are part of the new API. + // We will check if it is available. If not, we will use the old decoding API. + bool newParametersAPIAvailable{}; + std::function avcodec_send_packet; + std::function avcodec_receive_frame; + std::function + avcodec_parameters_to_context; + // This is the old API + std::function avcodec_decode_video2; +}; + +std::optional tryBindAVCodecFunctionsFromLibrary(SharedLibraryLoader &lib, + Log & log); + +} // namespace LibFFmpeg::functions diff --git a/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AvUtilFunctions.cpp b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AvUtilFunctions.cpp new file mode 100644 index 000000000..e121b7c0d --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AvUtilFunctions.cpp @@ -0,0 +1,110 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "AvUtilFunctions.h" + +#include "Functions.h" + +namespace LibFFmpeg::functions +{ + +std::optional tryBindAVUtilFunctionsFromLibrary(SharedLibraryLoader &lib, Log &log) +{ + if (!lib) + { + log.push_back("Binding of avUtil functions failed. Library is not loaded."); + return {}; + } + + AvUtilFunctions functions; + + lib.tryResolveFunction(functions.avutil_version, "avutil_version"); + lib.tryResolveFunction(functions.av_frame_alloc, "av_frame_alloc"); + lib.tryResolveFunction(functions.av_frame_free, "av_frame_free"); + lib.tryResolveFunction(functions.av_mallocz, "av_mallocz"); + lib.tryResolveFunction(functions.av_dict_set, "av_dict_set"); + lib.tryResolveFunction(functions.av_dict_get, "av_dict_get"); + lib.tryResolveFunction(functions.av_frame_get_side_data, "av_frame_get_side_data"); + lib.tryResolveFunction(functions.av_frame_get_metadata, "av_frame_get_metadata"); + lib.tryResolveFunction(functions.av_log_set_callback, "av_log_set_callback"); + lib.tryResolveFunction(functions.av_log_set_level, "av_log_set_level"); + lib.tryResolveFunction(functions.av_pix_fmt_desc_get, "av_pix_fmt_desc_get"); + lib.tryResolveFunction(functions.av_pix_fmt_desc_next, "av_pix_fmt_desc_next"); + lib.tryResolveFunction(functions.av_pix_fmt_desc_get_id, "av_pix_fmt_desc_get_id"); + + std::vector missingFunctions; + + checkForMissingFunctionAndLog(functions.avutil_version, "avutil_version", missingFunctions, log); + if (!functions.avutil_version) + { + log.push_back("Binding avutil functions failed.Missing function avutil_version"); + return {}; + } + + const auto version = Version::fromFFmpegVersion(functions.avutil_version()); + + checkForMissingFunctionAndLog(functions.av_frame_alloc, "av_frame_alloc", missingFunctions, log); + checkForMissingFunctionAndLog(functions.av_frame_free, "av_frame_free", missingFunctions, log); + checkForMissingFunctionAndLog(functions.av_frame_free, "av_frame_free", missingFunctions, log); + checkForMissingFunctionAndLog(functions.av_mallocz, "av_mallocz", missingFunctions, log); + checkForMissingFunctionAndLog(functions.av_dict_set, "av_dict_set", missingFunctions, log); + checkForMissingFunctionAndLog(functions.av_dict_get, "av_dict_get", missingFunctions, log); + checkForMissingFunctionAndLog( + functions.av_frame_get_side_data, "av_frame_get_side_data", missingFunctions, log); + + if (version.major < 57) + checkForMissingFunctionAndLog( + functions.av_frame_get_metadata, "av_frame_get_metadata", missingFunctions, log); + + checkForMissingFunctionAndLog( + functions.av_log_set_callback, "av_log_set_callback", missingFunctions, log); + checkForMissingFunctionAndLog( + functions.av_log_set_level, "av_log_set_level", missingFunctions, log); + checkForMissingFunctionAndLog( + functions.av_pix_fmt_desc_get, "av_pix_fmt_desc_get", missingFunctions, log); + checkForMissingFunctionAndLog( + functions.av_pix_fmt_desc_next, "av_pix_fmt_desc_next", missingFunctions, log); + checkForMissingFunctionAndLog( + functions.av_pix_fmt_desc_get_id, "av_pix_fmt_desc_get_id", missingFunctions, log); + + if (!missingFunctions.empty()) + { + log.push_back("Binding avUtil functions failed. Missing functions: " + + to_string(missingFunctions)); + return {}; + } + + log.push_back("Binding of avUtil functions successful."); + return functions; +} + +} // namespace LibFFmpeg::functions diff --git a/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AvUtilFunctions.h b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AvUtilFunctions.h new file mode 100644 index 000000000..0827157ab --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/AvUtilFunctions.h @@ -0,0 +1,65 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include + +namespace LibFFmpeg::functions +{ + +struct AvUtilFunctions +{ + std::function avutil_version; + std::function av_frame_alloc; + std::function av_frame_free; + std::function av_mallocz; + std::function av_dict_set; + std::function + av_dict_get; + std::function + av_frame_get_side_data; + std::function av_frame_get_metadata; + std::function av_log_set_callback; + std::function av_log_set_level; + std::function av_pix_fmt_desc_get; + std::function av_pix_fmt_desc_next; + std::function av_pix_fmt_desc_get_id; +}; + +std::optional tryBindAVUtilFunctionsFromLibrary(SharedLibraryLoader &lib, + Log & log); + +} // namespace LibFFmpeg::functions diff --git a/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/Functions.cpp b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/Functions.cpp new file mode 100644 index 000000000..2bf0d52ac --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/Functions.cpp @@ -0,0 +1,62 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "Functions.h" + +namespace LibFFmpeg::functions +{ + +std::string to_string(std::vector strings) +{ + std::ostringstream stream; + for (auto it = strings.begin(); it != strings.end(); it++) + { + if (it != strings.begin()) + stream << ", "; + stream << (*it); + } + return stream.str(); +} + +std::string logMissingFunctionsAndGetErrorMessage(const std::vector &missingFunctions, + const std::string libraryName, + Log & log) +{ + assert(!missingFunctions.empty()); + + const auto errorMessage = "Binding " + libraryName + + " functions failed. Missing functions: " + to_string(missingFunctions); + log.push_back(errorMessage); + return errorMessage; +} + +} // namespace LibFFmpeg::functions diff --git a/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/Functions.h b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/Functions.h new file mode 100644 index 000000000..1f3adfed0 --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/Functions.h @@ -0,0 +1,69 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include + +#include +#include +#include + +namespace LibFFmpeg::functions +{ + +using LoadingResult = tl::expected; +using LoadingResultAndLog = std::pair; + +template +void checkForMissingFunctionAndLog(std::function & function, + std::string name, + std::vector &missingFunctions, + Log & log) +{ + if (function) + log.push_back("Successfully resolved function " + name); + else + { + log.push_back("Failed to resolved function " + name); + missingFunctions.push_back(name); + } +} + +std::string to_string(std::vector strings); + +std::string logMissingFunctionsAndGetErrorMessage(const std::vector &missingFunctions, + const std::string libraryName, + Log & log); + +} // namespace LibFFmpeg::functions diff --git a/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/SwResampleFunctions.cpp b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/SwResampleFunctions.cpp new file mode 100644 index 000000000..0f240b4cc --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/SwResampleFunctions.cpp @@ -0,0 +1,69 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "SwResampleFunctions.h" + +#include "Functions.h" + +namespace LibFFmpeg::functions +{ + +std::optional tryBindSwResampleFunctionsFromLibrary(SharedLibraryLoader &lib, + Log & log) +{ + if (!lib) + { + log.push_back("Binding of swResample functions failed. Library is not loaded."); + return {}; + } + + SwResampleFunctions functions; + + lib.tryResolveFunction(functions.swresample_version, "swresample_version"); + + std::vector missingFunctions; + + checkForMissingFunctionAndLog( + functions.swresample_version, "swresample_version", missingFunctions, log); + + if (!missingFunctions.empty()) + { + log.push_back("Binding swResample functions failed. Missing functions: " + + to_string(missingFunctions)); + return {}; + } + + log.push_back("Binding of swPresample functions successful."); + return functions; +} + +} // namespace LibFFmpeg::functions diff --git a/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/SwResampleFunctions.h b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/SwResampleFunctions.h new file mode 100644 index 000000000..41f1c8a58 --- /dev/null +++ b/YUViewLib/externalLibs/LibFFmpeg++/libHandling/libraryFunctions/SwResampleFunctions.h @@ -0,0 +1,50 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include + +namespace LibFFmpeg::functions +{ + +struct SwResampleFunctions +{ + std::function swresample_version; +}; + +std::optional tryBindSwResampleFunctionsFromLibrary(SharedLibraryLoader &lib, + Log & log); + +} // namespace LibFFmpeg::functions diff --git a/YUViewLib/src/ffmpeg/AVCodecContextWrapper.cpp b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecContextWrapper.cpp similarity index 99% rename from YUViewLib/src/ffmpeg/AVCodecContextWrapper.cpp rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecContextWrapper.cpp index 6b7be6559..98b51c624 100644 --- a/YUViewLib/src/ffmpeg/AVCodecContextWrapper.cpp +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecContextWrapper.cpp @@ -33,7 +33,7 @@ #include "AVCodecContextWrapper.h" #include -namespace FFmpeg +namespace LibFFmpeg { namespace @@ -820,4 +820,4 @@ void AVCodecContextWrapper::update() throw std::runtime_error("Invalid library version"); } -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/AVCodecContextWrapper.h b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecContextWrapper.h similarity index 98% rename from YUViewLib/src/ffmpeg/AVCodecContextWrapper.h rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecContextWrapper.h index 2c7422010..6ad720f14 100644 --- a/YUViewLib/src/ffmpeg/AVCodecContextWrapper.h +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecContextWrapper.h @@ -32,10 +32,9 @@ #pragma once -#include "FFMpegLibrariesTypes.h" -#include +#include -namespace FFmpeg +namespace LibFFmpeg { class AVCodecContextWrapper @@ -145,4 +144,4 @@ class AVCodecContextWrapper LibraryVersions libraryVersions{}; }; -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/AVCodecIDWrapper.h b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecIDWrapper.h similarity index 96% rename from YUViewLib/src/ffmpeg/AVCodecIDWrapper.h rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecIDWrapper.h index 66c7a1341..8fadd22b6 100644 --- a/YUViewLib/src/ffmpeg/AVCodecIDWrapper.h +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecIDWrapper.h @@ -32,9 +32,9 @@ #pragma once -#include "FFMpegLibrariesTypes.h" +#include -namespace FFmpeg +namespace LibFFmpeg { class AVCodecIDWrapper @@ -72,4 +72,4 @@ class AVCodecIDWrapper std::string codecName; }; -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/AVCodecParametersWrapper.cpp b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecParametersWrapper.cpp similarity index 99% rename from YUViewLib/src/ffmpeg/AVCodecParametersWrapper.cpp rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecParametersWrapper.cpp index 2b2e2870f..661130bb5 100644 --- a/YUViewLib/src/ffmpeg/AVCodecParametersWrapper.cpp +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecParametersWrapper.cpp @@ -33,7 +33,7 @@ #include "AVCodecParametersWrapper.h" #include -namespace FFmpeg +namespace LibFFmpeg { namespace @@ -45,7 +45,7 @@ typedef struct AVCodecParameters_57_58_59_60 AVMediaType codec_type; AVCodecID codec_id; uint32_t codec_tag; - uint8_t *extradata; + uint8_t * extradata; int extradata_size; int format; int64_t bit_rate; @@ -69,7 +69,7 @@ typedef struct AVCodecParameters_57_58_59_60 } // namespace -AVCodecParametersWrapper::AVCodecParametersWrapper(AVCodecParameters *p, +AVCodecParametersWrapper::AVCodecParametersWrapper(AVCodecParameters * p, const LibraryVersions &libraryVersions) { this->param = p; @@ -407,4 +407,4 @@ void AVCodecParametersWrapper::update() throw std::runtime_error("Invalid library version"); } -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/AVCodecParametersWrapper.h b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecParametersWrapper.h similarity index 97% rename from YUViewLib/src/ffmpeg/AVCodecParametersWrapper.h rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecParametersWrapper.h index 365803bd8..e639e4c41 100644 --- a/YUViewLib/src/ffmpeg/AVCodecParametersWrapper.h +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecParametersWrapper.h @@ -32,10 +32,9 @@ #pragma once -#include "FFMpegLibrariesTypes.h" -#include +#include -namespace FFmpeg +namespace LibFFmpeg { class AVCodecParametersWrapper { @@ -96,4 +95,4 @@ class AVCodecParametersWrapper LibraryVersions libraryVersions{}; }; -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/AVCodecWrapper.cpp b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecWrapper.cpp similarity index 99% rename from YUViewLib/src/ffmpeg/AVCodecWrapper.cpp rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecWrapper.cpp index 70192f2d9..d65519a3f 100644 --- a/YUViewLib/src/ffmpeg/AVCodecWrapper.cpp +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecWrapper.cpp @@ -33,7 +33,7 @@ #include "AVCodecWrapper.h" #include -namespace FFmpeg +namespace LibFFmpeg { namespace @@ -153,4 +153,4 @@ void AVCodecWrapper::update() throw std::runtime_error("Invalid library version"); } -} // namespace FFmpeg \ No newline at end of file +} // namespace LibFFmpeg \ No newline at end of file diff --git a/YUViewLib/src/ffmpeg/AVCodecWrapper.h b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecWrapper.h similarity index 96% rename from YUViewLib/src/ffmpeg/AVCodecWrapper.h rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecWrapper.h index 96e8eb48e..ef1cbe408 100644 --- a/YUViewLib/src/ffmpeg/AVCodecWrapper.h +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVCodecWrapper.h @@ -32,11 +32,11 @@ #pragma once -#include "FFMpegLibrariesTypes.h" +#include #include -namespace FFmpeg +namespace LibFFmpeg { class AVCodecWrapper @@ -71,4 +71,4 @@ class AVCodecWrapper LibraryVersions libraryVersions; }; -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/AVDictionaryWrapper.h b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVDictionaryWrapper.h similarity index 95% rename from YUViewLib/src/ffmpeg/AVDictionaryWrapper.h rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVDictionaryWrapper.h index 7818a31d8..728963d2a 100644 --- a/YUViewLib/src/ffmpeg/AVDictionaryWrapper.h +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVDictionaryWrapper.h @@ -32,9 +32,9 @@ #pragma once -#include "FFMpegLibrariesTypes.h" +#include -namespace FFmpeg +namespace LibFFmpeg { class AVDictionaryWrapper @@ -51,4 +51,4 @@ class AVDictionaryWrapper AVDictionary *dict{}; }; -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/AVFormatContextWrapper.cpp b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVFormatContextWrapper.cpp similarity index 99% rename from YUViewLib/src/ffmpeg/AVFormatContextWrapper.cpp rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVFormatContextWrapper.cpp index c9b9475d3..ce2953e03 100644 --- a/YUViewLib/src/ffmpeg/AVFormatContextWrapper.cpp +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVFormatContextWrapper.cpp @@ -33,7 +33,7 @@ #include "AVFormatContextWrapper.h" #include "AVStreamWrapper.h" -namespace FFmpeg +namespace LibFFmpeg { namespace @@ -411,4 +411,4 @@ QStringPairList AVFormatContextWrapper::getInfoText() return info; } -} // namespace FFmpeg \ No newline at end of file +} // namespace LibFFmpeg \ No newline at end of file diff --git a/YUViewLib/src/ffmpeg/AVFormatContextWrapper.h b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVFormatContextWrapper.h similarity index 97% rename from YUViewLib/src/ffmpeg/AVFormatContextWrapper.h rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVFormatContextWrapper.h index 46badd931..e09b0a76c 100644 --- a/YUViewLib/src/ffmpeg/AVFormatContextWrapper.h +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVFormatContextWrapper.h @@ -36,10 +36,10 @@ #include "AVInputFormatWrapper.h" #include "AVPacketWrapper.h" #include "AVStreamWrapper.h" -#include "FFMpegLibrariesTypes.h" -#include -namespace FFmpeg +#include + +namespace LibFFmpeg { class AVFormatContextWrapper @@ -94,4 +94,4 @@ class AVFormatContextWrapper LibraryVersions libraryVersions{}; }; -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/AVFrameSideDataWrapper.cpp b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVFrameSideDataWrapper.cpp similarity index 98% rename from YUViewLib/src/ffmpeg/AVFrameSideDataWrapper.cpp rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVFrameSideDataWrapper.cpp index a71aaae5a..281f9661b 100644 --- a/YUViewLib/src/ffmpeg/AVFrameSideDataWrapper.cpp +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVFrameSideDataWrapper.cpp @@ -33,7 +33,7 @@ #include "AVFrameSideDataWrapper.h" #include -namespace FFmpeg +namespace LibFFmpeg { namespace @@ -95,4 +95,4 @@ std::vector AVFrameSideDataWrapper::getMotionVectors() const throw std::runtime_error("Invalid library version"); } -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/AVFrameSideDataWrapper.h b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVFrameSideDataWrapper.h similarity index 94% rename from YUViewLib/src/ffmpeg/AVFrameSideDataWrapper.h rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVFrameSideDataWrapper.h index a626091da..007f1266f 100644 --- a/YUViewLib/src/ffmpeg/AVFrameSideDataWrapper.h +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVFrameSideDataWrapper.h @@ -32,10 +32,10 @@ #pragma once -#include "FFMpegLibrariesTypes.h" -#include "MotionVector.h" +#include +#include -namespace FFmpeg +namespace LibFFmpeg { class AVFrameSideDataWrapper @@ -53,4 +53,4 @@ class AVFrameSideDataWrapper LibraryVersions libraryVersions{}; }; -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/AVFrameWrapper.cpp b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVFrameWrapper.cpp similarity index 99% rename from YUViewLib/src/ffmpeg/AVFrameWrapper.cpp rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVFrameWrapper.cpp index 53da0c068..8d5aacfc8 100644 --- a/YUViewLib/src/ffmpeg/AVFrameWrapper.cpp +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVFrameWrapper.cpp @@ -33,7 +33,7 @@ #include "AVFrameWrapper.h" #include -namespace FFmpeg +namespace LibFFmpeg { namespace @@ -277,4 +277,4 @@ void AVFrameWrapper::update() throw std::runtime_error("Invalid library version"); } -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/AVFrameWrapper.h b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVFrameWrapper.h similarity index 96% rename from YUViewLib/src/ffmpeg/AVFrameWrapper.h rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVFrameWrapper.h index c4b05992c..4dd65ef52 100644 --- a/YUViewLib/src/ffmpeg/AVFrameWrapper.h +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVFrameWrapper.h @@ -32,10 +32,9 @@ #pragma once -#include "FFMpegLibrariesTypes.h" -#include +#include -namespace FFmpeg +namespace LibFFmpeg { class AVFrameWrapper @@ -84,4 +83,4 @@ class AVFrameWrapper LibraryVersions libraryVersions{}; }; -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/AVInputFormatWrapper.cpp b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVInputFormatWrapper.cpp similarity index 98% rename from YUViewLib/src/ffmpeg/AVInputFormatWrapper.cpp rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVInputFormatWrapper.cpp index 16cd2d955..561f0aebe 100644 --- a/YUViewLib/src/ffmpeg/AVInputFormatWrapper.cpp +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVInputFormatWrapper.cpp @@ -32,7 +32,7 @@ #include "AVInputFormatWrapper.h" -namespace FFmpeg +namespace LibFFmpeg { namespace @@ -81,4 +81,4 @@ void AVInputFormatWrapper::update() } } -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/AVInputFormatWrapper.h b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVInputFormatWrapper.h similarity index 96% rename from YUViewLib/src/ffmpeg/AVInputFormatWrapper.h rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVInputFormatWrapper.h index 0372b2c3c..30f646f2f 100644 --- a/YUViewLib/src/ffmpeg/AVInputFormatWrapper.h +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVInputFormatWrapper.h @@ -32,9 +32,9 @@ #pragma once -#include "FFMpegLibrariesTypes.h" +#include -namespace FFmpeg +namespace LibFFmpeg { class AVInputFormatWrapper @@ -60,4 +60,4 @@ class AVInputFormatWrapper LibraryVersions libraryVersions{}; }; -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/AVPacketWrapper.cpp b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVPacketWrapper.cpp similarity index 99% rename from YUViewLib/src/ffmpeg/AVPacketWrapper.cpp rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVPacketWrapper.cpp index 06c64b4df..658fe92ca 100644 --- a/YUViewLib/src/ffmpeg/AVPacketWrapper.cpp +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVPacketWrapper.cpp @@ -34,7 +34,7 @@ #include #include -namespace FFmpeg +namespace LibFFmpeg { namespace @@ -416,4 +416,4 @@ void AVPacketWrapper::update() throw std::runtime_error("Invalid library version"); } -} // namespace FFmpeg +} // namespace LibFFmpeg diff --git a/YUViewLib/src/ffmpeg/AVPacketWrapper.h b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVPacketWrapper.h similarity index 98% rename from YUViewLib/src/ffmpeg/AVPacketWrapper.h rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVPacketWrapper.h index fb62b484e..15f1b4bdb 100644 --- a/YUViewLib/src/ffmpeg/AVPacketWrapper.h +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVPacketWrapper.h @@ -32,9 +32,9 @@ #pragma once -#include "FFMpegLibrariesTypes.h" +#include -namespace FFmpeg +namespace LibFFmpeg { // AVPacket data can be in one of two formats: @@ -171,4 +171,4 @@ class AVPacketWrapper PacketDataFormat packetFormat{PacketDataFormat::Unknown}; }; -} // namespace FFmpeg \ No newline at end of file +} // namespace LibFFmpeg \ No newline at end of file diff --git a/YUViewLib/src/ffmpeg/AVPixFmtDescriptorWrapper.cpp b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVPixFmtDescriptorWrapper.cpp similarity index 99% rename from YUViewLib/src/ffmpeg/AVPixFmtDescriptorWrapper.cpp rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVPixFmtDescriptorWrapper.cpp index 28c133bff..89afdb2d5 100644 --- a/YUViewLib/src/ffmpeg/AVPixFmtDescriptorWrapper.cpp +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVPixFmtDescriptorWrapper.cpp @@ -38,7 +38,7 @@ using PixelFormatYUV = video::yuv::PixelFormatYUV; using namespace std::rel_ops; -namespace FFmpeg +namespace LibFFmpeg { namespace @@ -406,4 +406,4 @@ bool AVPixFmtDescriptorWrapper::operator==(const AVPixFmtDescriptorWrapper &othe return true; } -} // namespace FFmpeg \ No newline at end of file +} // namespace LibFFmpeg \ No newline at end of file diff --git a/YUViewLib/src/ffmpeg/AVPixFmtDescriptorWrapper.h b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVPixFmtDescriptorWrapper.h similarity index 97% rename from YUViewLib/src/ffmpeg/AVPixFmtDescriptorWrapper.h rename to YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVPixFmtDescriptorWrapper.h index ee7390326..6acbd3037 100644 --- a/YUViewLib/src/ffmpeg/AVPixFmtDescriptorWrapper.h +++ b/YUViewLib/externalLibs/LibFFmpeg++/wrappers/AVPixFmtDescriptorWrapper.h @@ -32,12 +32,12 @@ #pragma once -#include "FFMpegLibrariesTypes.h" +#include #include