Skip to content

Commit

Permalink
cleanup: Slightly nicer code for the AV settings form.
Browse files Browse the repository at this point in the history
  • Loading branch information
iphydf committed Dec 24, 2024
1 parent 0d084d1 commit 95b45b6
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 79 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
53 changes: 1 addition & 52 deletions src/video/cameradevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ extern "C"
#pragma GCC diagnostic pop
}
#include "cameradevice.h"
#include "scopedavdictionary.h"
#include "src/persistence/settings.h"

#include <QDebug>
Expand Down Expand Up @@ -91,58 +92,6 @@ constexpr auto toCharArray()
// Compile-time unit test for the above function.
static_assert(toCharArray<12345>() == std::array<char, 6>{'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 <size_t N>
void operator=(const std::array<char, N>& 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
Expand Down
41 changes: 41 additions & 0 deletions src/video/scopedavdictionary.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include "scopedavdictionary.h"

#include <QString>

extern "C"
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
#include <libavformat/avformat.h>
#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;
}
45 changes: 45 additions & 0 deletions src/video/scopedavdictionary.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2024 The TokTok team.
*/

#pragma once

#include <array>
#include <cstddef>
#include <cstdint>

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 <std::size_t N>
void operator=(const std::array<char, N>& 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();
};
9 changes: 0 additions & 9 deletions src/video/videomode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
9 changes: 8 additions & 1 deletion src/video/videomode.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
33 changes: 16 additions & 17 deletions src/widget/form/settings/avform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <cassert>
#include <map>
#include <ranges>

#include <QDebug>
#include <QScreen>
Expand Down Expand Up @@ -214,27 +215,26 @@ void AVForm::selectBestModes(QVector<VideoMode>& allVideoModes)
}

// Identify the best resolutions available for the supposed XXXXp resolutions.
std::map<int, VideoMode> 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<std::pair<int, VideoMode>, 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<int, int> 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())
Expand All @@ -245,8 +245,7 @@ void AVForm::selectBestModes(QVector<VideoMode>& 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;
Expand All @@ -267,8 +266,8 @@ void AVForm::selectBestModes(QVector<VideoMode>& allVideoModes)
}

QVector<VideoMode> 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_);
Expand Down

0 comments on commit 95b45b6

Please sign in to comment.