chore(libvideo2x)!: replace the C API with C++ API (#1245)

* chore(libvideo2x)!: replace the C API with C++ API
* fix: convert wide string to u8 for av_opt_set
* style: removed unnecessary enum and struct specifiers

Signed-off-by: k4yt3x <i@k4yt3x.com>
This commit is contained in:
K4YT3X
2024-12-02 07:24:30 +00:00
committed by GitHub
parent 24d43a8478
commit f8dcad3aef
27 changed files with 420 additions and 457 deletions

View File

@@ -63,14 +63,13 @@ int64_t get_video_frame_count(AVFormatContext *ifmt_ctx, int in_vstream_idx) {
return static_cast<int64_t>(duration_secs * fps);
}
enum AVPixelFormat
get_encoder_default_pix_fmt(const AVCodec *encoder, AVPixelFormat target_pix_fmt) {
AVPixelFormat get_encoder_default_pix_fmt(const AVCodec *encoder, AVPixelFormat target_pix_fmt) {
int ret;
char errbuf[AV_ERROR_MAX_STRING_SIZE];
// Retrieve the list of supported pixel formats
#if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(61, 13, 100)
const enum AVPixelFormat *supported_pix_fmts = nullptr;
const AVPixelFormat *supported_pix_fmts = nullptr;
ret = avcodec_get_supported_config(
nullptr, encoder, AV_CODEC_CONFIG_PIX_FORMAT, 0, (const void **)&supported_pix_fmts, nullptr
);
@@ -90,7 +89,7 @@ get_encoder_default_pix_fmt(const AVCodec *encoder, AVPixelFormat target_pix_fmt
}
}
#else
const enum AVPixelFormat *supported_pix_fmts = encoder->pix_fmts;
const AVPixelFormat *supported_pix_fmts = encoder->pix_fmts;
#endif
// Determine if the target pixel format has an alpha channel
@@ -102,8 +101,8 @@ get_encoder_default_pix_fmt(const AVCodec *encoder, AVPixelFormat target_pix_fmt
}
// Iterate over supported pixel formats to find the best match
enum AVPixelFormat best_pix_fmt = AV_PIX_FMT_NONE;
for (const enum AVPixelFormat *p = supported_pix_fmts; *p != AV_PIX_FMT_NONE; p++) {
AVPixelFormat best_pix_fmt = AV_PIX_FMT_NONE;
for (const AVPixelFormat *p = supported_pix_fmts; *p != AV_PIX_FMT_NONE; p++) {
if (target_pix_fmt != AV_PIX_FMT_NONE) {
best_pix_fmt =
av_find_best_pix_fmt_of_2(best_pix_fmt, *p, target_pix_fmt, has_alpha, nullptr);

View File

@@ -2,7 +2,7 @@
#include <spdlog/spdlog.h>
enum AVPixelFormat Decoder::hw_pix_fmt_ = AV_PIX_FMT_NONE;
AVPixelFormat Decoder::hw_pix_fmt_ = AV_PIX_FMT_NONE;
Decoder::Decoder() : fmt_ctx_(nullptr), dec_ctx_(nullptr), in_vstream_idx_(-1) {}
@@ -17,8 +17,8 @@ Decoder::~Decoder() {
}
}
enum AVPixelFormat Decoder::get_hw_format(AVCodecContext *_, const enum AVPixelFormat *pix_fmts) {
for (const enum AVPixelFormat *p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) {
AVPixelFormat Decoder::get_hw_format(AVCodecContext *_, const AVPixelFormat *pix_fmts) {
for (const AVPixelFormat *p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) {
if (*p == hw_pix_fmt_) {
return *p;
}

View File

@@ -32,8 +32,8 @@ int Encoder::init(
const std::filesystem::path &out_fpath,
AVFormatContext *ifmt_ctx,
AVCodecContext *dec_ctx,
EncoderConfig *encoder_config,
const ProcessorConfig *processor_config,
EncoderConfig &enc_cfg,
const ProcessorConfig &proc_cfg,
int in_vstream_idx
) {
int ret;
@@ -46,10 +46,10 @@ int Encoder::init(
}
// Find the encoder
const AVCodec *encoder = avcodec_find_encoder(encoder_config->codec);
const AVCodec *encoder = avcodec_find_encoder(enc_cfg.codec);
if (!encoder) {
spdlog::error(
"Required video encoder not found for codec {}", avcodec_get_name(encoder_config->codec)
"Required video encoder not found for codec {}", avcodec_get_name(enc_cfg.codec)
);
return AVERROR_ENCODER_NOT_FOUND;
}
@@ -85,33 +85,33 @@ int Encoder::init(
enc_ctx_->sample_aspect_ratio = dec_ctx->sample_aspect_ratio;
// Set basic video options
enc_ctx_->width = encoder_config->width;
enc_ctx_->height = encoder_config->height;
enc_ctx_->width = enc_cfg.width;
enc_ctx_->height = enc_cfg.height;
// Set rate control and compression options
enc_ctx_->bit_rate = encoder_config->bit_rate;
enc_ctx_->rc_buffer_size = encoder_config->rc_buffer_size;
enc_ctx_->rc_min_rate = encoder_config->rc_min_rate;
enc_ctx_->rc_max_rate = encoder_config->rc_max_rate;
enc_ctx_->qmin = encoder_config->qmin;
enc_ctx_->qmax = encoder_config->qmax;
enc_ctx_->bit_rate = enc_cfg.bit_rate;
enc_ctx_->rc_buffer_size = enc_cfg.rc_buffer_size;
enc_ctx_->rc_min_rate = enc_cfg.rc_min_rate;
enc_ctx_->rc_max_rate = enc_cfg.rc_max_rate;
enc_ctx_->qmin = enc_cfg.qmin;
enc_ctx_->qmax = enc_cfg.qmax;
// Set GOP and frame structure options
enc_ctx_->gop_size = encoder_config->gop_size;
enc_ctx_->max_b_frames = encoder_config->max_b_frames;
enc_ctx_->keyint_min = encoder_config->keyint_min;
enc_ctx_->refs = encoder_config->refs;
enc_ctx_->gop_size = enc_cfg.gop_size;
enc_ctx_->max_b_frames = enc_cfg.max_b_frames;
enc_ctx_->keyint_min = enc_cfg.keyint_min;
enc_ctx_->refs = enc_cfg.refs;
// Set performance and threading options
enc_ctx_->thread_count = encoder_config->thread_count;
enc_ctx_->thread_count = enc_cfg.thread_count;
// Set latency and buffering options
enc_ctx_->delay = encoder_config->delay;
enc_ctx_->delay = enc_cfg.delay;
// Set the pixel format
if (encoder_config->pix_fmt != AV_PIX_FMT_NONE) {
if (enc_cfg.pix_fmt != AV_PIX_FMT_NONE) {
// Use the specified pixel format
enc_ctx_->pix_fmt = encoder_config->pix_fmt;
enc_ctx_->pix_fmt = enc_cfg.pix_fmt;
} else {
// Automatically select the pixel format
enc_ctx_->pix_fmt = get_encoder_default_pix_fmt(encoder, dec_ctx->pix_fmt);
@@ -122,11 +122,9 @@ int Encoder::init(
spdlog::debug("Auto-selected pixel format: {}", av_get_pix_fmt_name(enc_ctx_->pix_fmt));
}
if (processor_config->frm_rate_mul > 0) {
if (proc_cfg.frm_rate_mul > 0) {
AVRational in_frame_rate = get_video_frame_rate(ifmt_ctx, in_vstream_idx);
enc_ctx_->framerate = {
in_frame_rate.num * processor_config->frm_rate_mul, in_frame_rate.den
};
enc_ctx_->framerate = {in_frame_rate.num * proc_cfg.frm_rate_mul, in_frame_rate.den};
enc_ctx_->time_base = av_inv_q(enc_ctx_->framerate);
} else {
// Set the output video's time base
@@ -145,13 +143,13 @@ int Encoder::init(
}
// Set extra AVOptions
for (size_t i = 0; i < encoder_config->nb_extra_options; i++) {
const char *key = encoder_config->extra_options[i].key;
const char *value = encoder_config->extra_options[i].value;
spdlog::debug("Setting encoder option '{}' to '{}'", key, value);
for (const auto &[opt_name, opt_value] : enc_cfg.extra_opts) {
std::string opt_name_str = wstring_to_u8string(opt_name);
std::string opt_value_str = wstring_to_u8string(opt_value);
spdlog::debug("Setting encoder option '{}' to '{}'", opt_name_str, opt_value_str);
if (av_opt_set(enc_ctx_->priv_data, key, value, 0) < 0) {
spdlog::warn("Failed to set encoder option '{}' to '{}'", key, value);
if (av_opt_set(enc_ctx_->priv_data, opt_name_str.c_str(), opt_value_str.c_str(), 0) < 0) {
spdlog::warn("Failed to set encoder option '{}' to '{}'", opt_name_str, opt_value_str);
}
}
@@ -178,7 +176,7 @@ int Encoder::init(
out_vstream->r_frame_rate = enc_ctx_->framerate;
// Copy other streams if necessary
if (encoder_config->copy_streams) {
if (enc_cfg.copy_streams) {
// Allocate the stream mape frame o
stream_map_ =
reinterpret_cast<int *>(av_malloc_array(ifmt_ctx->nb_streams, sizeof(*stream_map_)));

View File

@@ -4,7 +4,6 @@
#include <spdlog/spdlog.h>
#include "char_defs.h"
#include "fsutils.h"
#include "libplacebo.h"
@@ -148,12 +147,12 @@ int FilterLibplacebo::flush(std::vector<AVFrame *> &flushed_frames) {
}
void FilterLibplacebo::get_output_dimensions(
const ProcessorConfig *processor_config,
const ProcessorConfig &proc_cfg,
int,
int,
int &out_width,
int &out_height
) const {
out_width = processor_config->width;
out_height = processor_config->height;
out_width = proc_cfg.width;
out_height = proc_cfg.height;
}

View File

@@ -121,7 +121,7 @@ int FilterRealesrgan::filter(AVFrame *in_frame, AVFrame **out_frame) {
}
void FilterRealesrgan::get_output_dimensions(
const ProcessorConfig *,
const ProcessorConfig &,
int in_width,
int in_height,
int &out_width,

View File

@@ -27,7 +27,7 @@ auto av_packet_deleter = [](AVPacket *packet) {
// Sets the total number of frames to process in the VideoProcessingContext
void set_total_frames(
const ProcessorConfig *processor_config,
const ProcessorConfig &proc_cfg,
VideoProcessingContext *proc_ctx,
AVFormatContext *ifmt_ctx,
int in_vstream_idx,
@@ -44,8 +44,8 @@ void set_total_frames(
}
// Set total frames for interpolation
if (processor->get_processing_mode() == PROCESSING_MODE_INTERPOLATE) {
proc_ctx->total_frames *= processor_config->frm_rate_mul;
if (processor->get_processing_mode() == ProcessingMode::Interpolate) {
proc_ctx->total_frames *= proc_cfg.frm_rate_mul;
}
}
@@ -126,7 +126,7 @@ int process_filtering(
int process_interpolation(
Processor *processor,
const ProcessorConfig *processor_config,
const ProcessorConfig &proc_cfg,
VideoProcessingContext *proc_ctx,
Encoder &encoder,
bool benchmark,
@@ -141,14 +141,14 @@ int process_interpolation(
Interpolator *interpolator = static_cast<Interpolator *>(processor);
// Calculate the time step for each frame
float time_step = 1.0f / static_cast<float>(processor_config->frm_rate_mul);
float time_step = 1.0f / static_cast<float>(proc_cfg.frm_rate_mul);
float current_time_step = time_step;
// Check if a scene change is detected
bool skip_frame = false;
if (prev_frame != nullptr) {
float frame_diff = get_frame_diff(prev_frame.get(), frame);
if (frame_diff > processor_config->scn_det_thresh) {
if (frame_diff > proc_cfg.scn_det_thresh) {
spdlog::debug(
"Scene change detected ({:.2f}%), skipping frame {}",
frame_diff,
@@ -159,7 +159,7 @@ int process_interpolation(
}
// Write the interpolated frames
for (int i = 0; i < processor_config->frm_rate_mul - 1; i++) {
for (int i = 0; i < proc_cfg.frm_rate_mul - 1; i++) {
// Skip interpolation if this is the first frame
if (prev_frame == nullptr) {
break;
@@ -206,8 +206,8 @@ int process_interpolation(
// Process frames using the selected filter.
int process_frames(
const EncoderConfig *encoder_config,
const ProcessorConfig *processor_config,
const EncoderConfig &enc_cfg,
const ProcessorConfig &proc_cfg,
VideoProcessingContext *proc_ctx,
Decoder &decoder,
Encoder &encoder,
@@ -245,7 +245,7 @@ int process_frames(
}
// Set the total number of frames in the VideoProcessingContext
set_total_frames(processor_config, proc_ctx, ifmt_ctx, in_vstream_idx, processor);
set_total_frames(proc_cfg, proc_ctx, ifmt_ctx, in_vstream_idx, processor);
// Read frames from the input file
while (!proc_ctx->abort) {
@@ -292,7 +292,7 @@ int process_frames(
// Process the frame based on the selected processing mode
switch (processor->get_processing_mode()) {
case PROCESSING_MODE_FILTER: {
case ProcessingMode::Filter: {
ret = process_filtering(
processor,
proc_ctx,
@@ -303,10 +303,10 @@ int process_frames(
);
break;
}
case PROCESSING_MODE_INTERPOLATE: {
case ProcessingMode::Interpolate: {
ret = process_interpolation(
processor,
processor_config,
proc_cfg,
proc_ctx,
encoder,
benchmark,
@@ -329,7 +329,7 @@ int process_frames(
"Processed frame {}/{}", proc_ctx->processed_frames, proc_ctx->total_frames
);
}
} else if (encoder_config->copy_streams && stream_map[packet->stream_index] >= 0) {
} else if (enc_cfg.copy_streams && stream_map[packet->stream_index] >= 0) {
write_raw_packet(packet.get(), ifmt_ctx, ofmt_ctx, stream_map);
}
av_packet_unref(packet.get());

View File

@@ -93,6 +93,33 @@ std::string path_to_u8string(const std::filesystem::path &path) {
#endif
}
#ifdef _WIN32
std::string wstring_to_u8string(const std::wstring &wstr) {
if (wstr.empty()) {
return std::string();
}
int size_needed = WideCharToMultiByte(
CP_UTF8, 0, wstr.data(), static_cast<int>(wstr.size()), nullptr, 0, nullptr, nullptr
);
std::string converted_str(size_needed, 0);
WideCharToMultiByte(
CP_UTF8,
0,
wstr.data(),
static_cast<int>(wstr.size()),
&converted_str[0],
size_needed,
nullptr,
nullptr
);
return converted_str;
}
#else
std::string wstring_to_u8string(const std::string &str) {
return str;
}
#endif
StringType path_to_string_type(const std::filesystem::path &path) {
#if _WIN32
return path.wstring();

View File

@@ -119,7 +119,7 @@ int InterpolatorRIFE::interpolate(
}
void InterpolatorRIFE::get_output_dimensions(
const ProcessorConfig *,
const ProcessorConfig &,
int in_width,
int in_height,
int &out_width,

View File

@@ -16,53 +16,15 @@ extern "C" {
#include "processor.h"
#include "processor_factory.h"
static void set_log_level(Libvideo2xLogLevel log_level) {
switch (log_level) {
case LIBVIDEO2X_LOG_LEVEL_TRACE:
av_log_set_level(AV_LOG_TRACE);
spdlog::set_level(spdlog::level::trace);
break;
case LIBVIDEO2X_LOG_LEVEL_DEBUG:
av_log_set_level(AV_LOG_DEBUG);
spdlog::set_level(spdlog::level::debug);
break;
case LIBVIDEO2X_LOG_LEVEL_INFO:
av_log_set_level(AV_LOG_INFO);
spdlog::set_level(spdlog::level::info);
break;
case LIBVIDEO2X_LOG_LEVEL_WARNING:
av_log_set_level(AV_LOG_WARNING);
spdlog::set_level(spdlog::level::warn);
break;
case LIBVIDEO2X_LOG_LEVEL_ERROR:
av_log_set_level(AV_LOG_ERROR);
spdlog::set_level(spdlog::level::err);
break;
case LIBVIDEO2X_LOG_LEVEL_CRITICAL:
av_log_set_level(AV_LOG_FATAL);
spdlog::set_level(spdlog::level::critical);
break;
case LIBVIDEO2X_LOG_LEVEL_OFF:
av_log_set_level(AV_LOG_QUIET);
spdlog::set_level(spdlog::level::off);
break;
default:
av_log_set_level(AV_LOG_INFO);
spdlog::set_level(spdlog::level::info);
break;
}
}
extern "C" int process_video(
const CharType *in_fname,
const CharType *out_fname,
int process_video(
const std::filesystem::path in_fname,
const std::filesystem::path out_fname,
const HardwareConfig hw_cfg,
const ProcessorConfig proc_cfg,
EncoderConfig enc_cfg,
VideoProcessingContext *proc_ctx,
Libvideo2xLogLevel log_level,
bool benchmark,
uint32_t vk_device_index,
AVHWDeviceType hw_type,
const ProcessorConfig *processor_config,
EncoderConfig *encoder_config,
VideoProcessingContext *proc_ctx
bool benchmark
) {
char errbuf[AV_ERROR_MAX_STRING_SIZE];
int ret = 0;
@@ -70,10 +32,6 @@ extern "C" int process_video(
// Set the log level for FFmpeg and spdlog
set_log_level(log_level);
// Convert the file names to std::filesystem::path
std::filesystem::path in_fpath(in_fname);
std::filesystem::path out_fpath(out_fname);
// Create a smart pointer to manage the hardware device context
auto hw_ctx_deleter = [](AVBufferRef *ref) {
if (ref != nullptr) {
@@ -83,9 +41,9 @@ extern "C" int process_video(
std::unique_ptr<AVBufferRef, decltype(hw_ctx_deleter)> hw_ctx(nullptr, hw_ctx_deleter);
// Initialize hardware device context
if (hw_type != AV_HWDEVICE_TYPE_NONE) {
if (hw_cfg.hw_device_type != AV_HWDEVICE_TYPE_NONE) {
AVBufferRef *tmp_hw_ctx = nullptr;
ret = av_hwdevice_ctx_create(&tmp_hw_ctx, hw_type, NULL, NULL, 0);
ret = av_hwdevice_ctx_create(&tmp_hw_ctx, hw_cfg.hw_device_type, NULL, NULL, 0);
if (ret < 0) {
av_strerror(ret, errbuf, sizeof(errbuf));
spdlog::critical("Error initializing hardware device context: {}", errbuf);
@@ -96,7 +54,7 @@ extern "C" int process_video(
// Initialize input decoder
Decoder decoder;
ret = decoder.init(hw_type, hw_ctx.get(), in_fpath);
ret = decoder.init(hw_cfg.hw_device_type, hw_ctx.get(), in_fname);
if (ret < 0) {
av_strerror(ret, errbuf, sizeof(errbuf));
spdlog::critical("Failed to initialize decoder: {}", errbuf);
@@ -109,7 +67,7 @@ extern "C" int process_video(
// Create and initialize the appropriate filter
std::unique_ptr<Processor> processor(
ProcessorFactory::instance().create_processor(processor_config, vk_device_index)
ProcessorFactory::instance().create_processor(proc_cfg, hw_cfg.vk_device_index)
);
if (processor == nullptr) {
spdlog::critical("Failed to create filter instance");
@@ -119,7 +77,7 @@ extern "C" int process_video(
// Initialize output dimensions based on filter configuration
int output_width = 0, output_height = 0;
processor->get_output_dimensions(
processor_config, dec_ctx->width, dec_ctx->height, output_width, output_height
proc_cfg, dec_ctx->width, dec_ctx->height, output_width, output_height
);
if (output_width <= 0 || output_height <= 0) {
spdlog::critical("Failed to determine the output dimensions");
@@ -127,14 +85,13 @@ extern "C" int process_video(
}
// Update encoder configuration with output dimensions
encoder_config->width = output_width;
encoder_config->height = output_height;
enc_cfg.width = output_width;
enc_cfg.height = output_height;
// Initialize the encoder
Encoder encoder;
ret = encoder.init(
hw_ctx.get(), out_fpath, ifmt_ctx, dec_ctx, encoder_config, processor_config, in_vstream_idx
);
ret =
encoder.init(hw_ctx.get(), out_fname, ifmt_ctx, dec_ctx, enc_cfg, proc_cfg, in_vstream_idx);
if (ret < 0) {
av_strerror(ret, errbuf, sizeof(errbuf));
spdlog::critical("Failed to initialize encoder: {}", errbuf);
@@ -149,9 +106,7 @@ extern "C" int process_video(
}
// Process frames using the encoder and decoder
ret = process_frames(
encoder_config, processor_config, proc_ctx, decoder, encoder, processor.get(), benchmark
);
ret = process_frames(enc_cfg, proc_cfg, proc_ctx, decoder, encoder, processor.get(), benchmark);
if (ret < 0) {
av_strerror(ret, errbuf, sizeof(errbuf));
spdlog::critical("Error processing frames: {}", errbuf);

44
src/logging.cpp Normal file
View File

@@ -0,0 +1,44 @@
#include "logging.h"
extern "C" {
#include <libavutil/avutil.h>
}
#include <spdlog/spdlog.h>
void set_log_level(Libvideo2xLogLevel log_level) {
switch (log_level) {
case Libvideo2xLogLevel::Trace:
av_log_set_level(AV_LOG_TRACE);
spdlog::set_level(spdlog::level::trace);
break;
case Libvideo2xLogLevel::Debug:
av_log_set_level(AV_LOG_DEBUG);
spdlog::set_level(spdlog::level::debug);
break;
case Libvideo2xLogLevel::Info:
av_log_set_level(AV_LOG_INFO);
spdlog::set_level(spdlog::level::info);
break;
case Libvideo2xLogLevel::Warning:
av_log_set_level(AV_LOG_WARNING);
spdlog::set_level(spdlog::level::warn);
break;
case Libvideo2xLogLevel::Error:
av_log_set_level(AV_LOG_ERROR);
spdlog::set_level(spdlog::level::err);
break;
case Libvideo2xLogLevel::Critical:
av_log_set_level(AV_LOG_FATAL);
spdlog::set_level(spdlog::level::critical);
break;
case Libvideo2xLogLevel::Off:
av_log_set_level(AV_LOG_QUIET);
spdlog::set_level(spdlog::level::off);
break;
default:
av_log_set_level(AV_LOG_INFO);
spdlog::set_level(spdlog::level::info);
break;
}
}

View File

@@ -28,32 +28,33 @@ void ProcessorFactory::register_processor(ProcessorType type, Creator creator) {
// Create a processor instance
std::unique_ptr<Processor> ProcessorFactory::create_processor(
const ProcessorConfig *processor_config,
const ProcessorConfig &proc_cfg,
uint32_t vk_device_index
) const {
auto it = creators.find(processor_config->processor_type);
auto it = creators.find(proc_cfg.processor_type);
if (it == creators.end()) {
spdlog::critical(
"Processor type not registered: {}", static_cast<int>(processor_config->processor_type)
"Processor type not registered: {}", static_cast<int>(proc_cfg.processor_type)
);
return nullptr;
}
// Call the corresponding creator function
return it->second(processor_config, vk_device_index);
return it->second(proc_cfg, vk_device_index);
}
// Initialize default processors
void ProcessorFactory::init_default_processors(ProcessorFactory &factory) {
factory.register_processor(
PROCESSOR_LIBPLACEBO,
[](const ProcessorConfig *config, uint32_t vk_device_index) -> std::unique_ptr<Processor> {
const auto &cfg = config->config.libplacebo;
if (!cfg.shader_path) {
ProcessorType::Libplacebo,
[](const ProcessorConfig &proc_cfg,
uint32_t vk_device_index) -> std::unique_ptr<Processor> {
const auto &config = std::get<LibplaceboConfig>(proc_cfg.config);
if (config.shader_path.empty()) {
spdlog::critical("Shader path must be provided for the libplacebo filter");
return nullptr;
}
if (config->width <= 0 || config->height <= 0) {
if (proc_cfg.width <= 0 || proc_cfg.height <= 0) {
spdlog::critical(
"Output width and height must be provided for the libplacebo filter"
);
@@ -61,39 +62,41 @@ void ProcessorFactory::init_default_processors(ProcessorFactory &factory) {
}
return std::make_unique<FilterLibplacebo>(
vk_device_index,
std::filesystem::path(cfg.shader_path),
config->width,
config->height
std::filesystem::path(config.shader_path),
proc_cfg.width,
proc_cfg.height
);
}
);
factory.register_processor(
PROCESSOR_REALESRGAN,
[](const ProcessorConfig *config, uint32_t vk_device_index) -> std::unique_ptr<Processor> {
const auto &cfg = config->config.realesrgan;
if (config->scaling_factor <= 0) {
ProcessorType::RealESRGAN,
[](const ProcessorConfig &proc_cfg,
uint32_t vk_device_index) -> std::unique_ptr<Processor> {
const auto &config = std::get<RealESRGANConfig>(proc_cfg.config);
if (proc_cfg.scaling_factor <= 0) {
spdlog::critical("Scaling factor must be provided for the RealESRGAN filter");
return nullptr;
}
if (!cfg.model_name) {
if (config.model_name.empty()) {
spdlog::critical("Model name must be provided for the RealESRGAN filter");
return nullptr;
}
return std::make_unique<FilterRealesrgan>(
static_cast<int>(vk_device_index),
cfg.tta_mode,
config->scaling_factor,
cfg.model_name
config.tta_mode,
proc_cfg.scaling_factor,
config.model_name
);
}
);
factory.register_processor(
PROCESSOR_RIFE,
[](const ProcessorConfig *config, uint32_t vk_device_index) -> std::unique_ptr<Processor> {
const auto &cfg = config->config.rife;
if (!cfg.model_name) {
ProcessorType::RIFE,
[](const ProcessorConfig &proc_cfg,
uint32_t vk_device_index) -> std::unique_ptr<Processor> {
const auto &cfg = std::get<RIFEConfig>(proc_cfg.config);
if (cfg.model_name.empty()) {
spdlog::critical("Model name must be provided for the RIFE filter");
return nullptr;
}