diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f9108e8ea..6b5083ab18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -443,6 +443,8 @@ set(${PROJECT_NAME}_SOURCES src/video/ivideosettings.h src/video/netcamview.cpp src/video/netcamview.h + src/video/scopedavdictionary.cpp + src/video/scopedavdictionary.h src/video/videoframe.cpp src/video/videoframe.h src/video/videomode.cpp diff --git a/src/video/cameradevice.cpp b/src/video/cameradevice.cpp index 02ade51403..be22cbe6af 100644 --- a/src/video/cameradevice.cpp +++ b/src/video/cameradevice.cpp @@ -15,6 +15,7 @@ extern "C" #pragma GCC diagnostic pop } #include "cameradevice.h" +#include "scopedavdictionary.h" #include "src/persistence/settings.h" #include @@ -91,58 +92,6 @@ constexpr auto toCharArray() // Compile-time unit test for the above function. static_assert(toCharArray<12345>() == std::array{'1', '2', '3', '4', '5', '\0'}); -class ScopedAVDictionary -{ - AVDictionary* options = nullptr; - - struct Setter - { - AVDictionary** dict; - const char* key; - - void operator=(const char* value) - { - av_dict_set(dict, key, value, 0); - } - - template - void operator=(const std::array& value) - { - *this = value.data(); - } - - void operator=(const QString& value) - { - *this = value.toStdString().c_str(); - } - - void operator=(int64_t value) - { - av_dict_set_int(dict, key, value, 0); - } - }; - -public: - ScopedAVDictionary() = default; - ScopedAVDictionary& operator=(const ScopedAVDictionary&) = delete; - ScopedAVDictionary(const ScopedAVDictionary&) = delete; - - ~ScopedAVDictionary() - { - av_dict_free(&options); - } - - Setter operator[](const char* key) - { - return {&options, key}; - } - - AVDictionary** get() - { - return &options; - } -}; - struct AVFormatContextDeleter { void operator()(AVFormatContext* ctx) const diff --git a/src/video/scopedavdictionary.cpp b/src/video/scopedavdictionary.cpp new file mode 100644 index 0000000000..a4a3aec5b2 --- /dev/null +++ b/src/video/scopedavdictionary.cpp @@ -0,0 +1,41 @@ +#include "scopedavdictionary.h" + +#include + +extern "C" +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#include +#pragma GCC diagnostic pop +} + +void ScopedAVDictionary::Setter::operator=(const char* value) +{ + av_dict_set(dict, key, value, 0); +} + +void ScopedAVDictionary::Setter::operator=(const QString& value) +{ + *this = value.toStdString().c_str(); +} + +void ScopedAVDictionary::Setter::operator=(std::int64_t value) +{ + av_dict_set_int(dict, key, value, 0); +} + +ScopedAVDictionary::~ScopedAVDictionary() +{ + av_dict_free(&options); +} + +ScopedAVDictionary::Setter ScopedAVDictionary::operator[](const char* key) +{ + return {&options, key}; +} + +AVDictionary** ScopedAVDictionary::get() +{ + return &options; +} diff --git a/src/video/scopedavdictionary.h b/src/video/scopedavdictionary.h new file mode 100644 index 0000000000..79a7588910 --- /dev/null +++ b/src/video/scopedavdictionary.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2024 The TokTok team. + */ + +#pragma once + +#include +#include +#include + +struct AVDictionary; +class QString; + +class ScopedAVDictionary +{ + AVDictionary* options = nullptr; + + struct Setter + { + AVDictionary** dict; + const char* key; + + void operator=(const char* value); + void operator=(const QString& value); + + template + void operator=(const std::array& value) + { + *this = value.data(); + } + + void operator=(std::int64_t value); + }; + +public: + ScopedAVDictionary() = default; + ScopedAVDictionary& operator=(const ScopedAVDictionary&) = delete; + ScopedAVDictionary(const ScopedAVDictionary&) = delete; + + ~ScopedAVDictionary(); + + Setter operator[](const char* key); + + AVDictionary** get(); +}; diff --git a/src/video/videomode.cpp b/src/video/videomode.cpp index 6fade31356..67170810f3 100644 --- a/src/video/videomode.cpp +++ b/src/video/videomode.cpp @@ -20,15 +20,6 @@ * @note a value < 0 indicates an invalid value */ -VideoMode::VideoMode(int width_, int height_, int x_, int y_, float fps_) - : width(width_) - , height(height_) - , x(x_) - , y(y_) - , fps(fps_) -{ -} - VideoMode::VideoMode(QRect rect) : width(rect.width()) , height(rect.height()) diff --git a/src/video/videomode.h b/src/video/videomode.h index d18b3bac73..1e1693f150 100644 --- a/src/video/videomode.h +++ b/src/video/videomode.h @@ -15,7 +15,14 @@ struct VideoMode float fps = -1.0f; uint32_t pixel_format = 0; - explicit VideoMode(int width = 0, int height = 0, int x = 0, int y = 0, float fps = -1.0f); + explicit constexpr VideoMode(int width_ = 0, int height_ = 0, int x_ = 0, int y_ = 0, float fps_ = -1.0f) + : width(width_) + , height(height_) + , x(x_) + , y(y_) + , fps(fps_) + { + } explicit VideoMode(QRect rect); diff --git a/src/widget/form/settings/avform.cpp b/src/widget/form/settings/avform.cpp index 6df251334d..c26784994c 100644 --- a/src/widget/form/settings/avform.cpp +++ b/src/widget/form/settings/avform.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -214,27 +215,26 @@ void AVForm::selectBestModes(QVector& allVideoModes) } // Identify the best resolutions available for the supposed XXXXp resolutions. - std::map idealModes; - idealModes[120] = VideoMode(160, 120); - idealModes[240] = VideoMode(430, 240); - idealModes[360] = VideoMode(640, 360); - idealModes[480] = VideoMode(854, 480); - idealModes[720] = VideoMode(1280, 720); - idealModes[1080] = VideoMode(1920, 1080); - idealModes[1440] = VideoMode(2560, 1440); - idealModes[2160] = VideoMode(3840, 2160); + constexpr std::array, 8> idealModes{{ + {120, VideoMode(160, 120)}, // 1 + {240, VideoMode(430, 240)}, // 2 + {360, VideoMode(640, 360)}, // 3 + {480, VideoMode(854, 480)}, // 4 + {720, VideoMode(1280, 720)}, // 5 + {1080, VideoMode(1920, 1080)}, // 6 + {1440, VideoMode(2560, 1440)}, // 7 + {2160, VideoMode(3840, 2160)}, // 8 + }}; std::map bestModeIndices; for (int i = 0; i < allVideoModes.size(); ++i) { - VideoMode mode = allVideoModes[i]; + const VideoMode mode = allVideoModes[i]; // PS3-Cam protection, everything above 60fps makes no sense if (mode.fps > 60) continue; - for (auto iter = idealModes.begin(); iter != idealModes.end(); ++iter) { - int res = iter->first; - VideoMode idealMode = iter->second; + for (const auto& [res, idealMode] : idealModes) { // don't take approximately correct resolutions unless they really // are close if (mode.norm(idealMode) > idealMode.tolerance()) @@ -245,8 +245,7 @@ void AVForm::selectBestModes(QVector& allVideoModes) continue; } - int index = bestModeIndices[res]; - VideoMode best = allVideoModes[index]; + const VideoMode best = allVideoModes[bestModeIndices[res]]; if (mode.norm(idealMode) < best.norm(idealMode)) { bestModeIndices[res] = i; continue; @@ -267,8 +266,8 @@ void AVForm::selectBestModes(QVector& allVideoModes) } QVector newVideoModes; - for (auto it = bestModeIndices.rbegin(); it != bestModeIndices.rend(); ++it) { - VideoMode mode_ = allVideoModes[it->second]; + for (const auto& [_, modeIndex] : std::views::reverse(bestModeIndices)) { + VideoMode mode_ = allVideoModes[modeIndex]; if (newVideoModes.empty()) { newVideoModes.push_back(mode_);