code: Migrate encoder::ffmpeg to modern handler loader
A different version of the dynamic loader allows us to simply register handlers at load time, instead of requiring custom code. Could also make it so that it loads them when needed, but since they're mostly static code, this won't matter much.
This commit is contained in:
parent
a1968b970b
commit
c4461e70b9
|
@ -10,7 +10,6 @@
|
||||||
#include "strings.hpp"
|
#include "strings.hpp"
|
||||||
#include "codecs/hevc.hpp"
|
#include "codecs/hevc.hpp"
|
||||||
#include "ffmpeg/tools.hpp"
|
#include "ffmpeg/tools.hpp"
|
||||||
#include "handlers/debug_handler.hpp"
|
|
||||||
#include "obs/gs/gs-helper.hpp"
|
#include "obs/gs/gs-helper.hpp"
|
||||||
#include "plugin.hpp"
|
#include "plugin.hpp"
|
||||||
|
|
||||||
|
@ -32,24 +31,6 @@ extern "C" {
|
||||||
#include "warning-enable.hpp"
|
#include "warning-enable.hpp"
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_ENCODER_FFMPEG_AMF
|
|
||||||
#include "handlers/amf_h264_handler.hpp"
|
|
||||||
#include "handlers/amf_hevc_handler.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_ENCODER_FFMPEG_NVENC
|
|
||||||
#include "handlers/nvenc_h264_handler.hpp"
|
|
||||||
#include "handlers/nvenc_hevc_handler.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_ENCODER_FFMPEG_PRORES
|
|
||||||
#include "handlers/prores_aw_handler.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_ENCODER_FFMPEG_DNXHR
|
|
||||||
#include "handlers/dnxhd_handler.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include "ffmpeg/hwapi/d3d11.hpp"
|
#include "ffmpeg/hwapi/d3d11.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
@ -176,7 +157,7 @@ ffmpeg_instance::~ffmpeg_instance()
|
||||||
void ffmpeg_instance::get_properties(obs_properties_t* props)
|
void ffmpeg_instance::get_properties(obs_properties_t* props)
|
||||||
{
|
{
|
||||||
if (_handler)
|
if (_handler)
|
||||||
_handler->get_properties(props, _codec, _context, _handler->is_hardware_encoder(_factory));
|
_handler->properties(this->_factory, this, props);
|
||||||
|
|
||||||
obs_property_set_enabled(obs_properties_get(props, ST_KEY_KEYFRAMES_INTERVALTYPE), false);
|
obs_property_set_enabled(obs_properties_get(props, ST_KEY_KEYFRAMES_INTERVALTYPE), false);
|
||||||
obs_property_set_enabled(obs_properties_get(props, ST_KEY_KEYFRAMES_INTERVAL_SECONDS), false);
|
obs_property_set_enabled(obs_properties_get(props, ST_KEY_KEYFRAMES_INTERVAL_SECONDS), false);
|
||||||
|
@ -189,7 +170,7 @@ void ffmpeg_instance::get_properties(obs_properties_t* props)
|
||||||
void ffmpeg_instance::migrate(obs_data_t* settings, uint64_t version)
|
void ffmpeg_instance::migrate(obs_data_t* settings, uint64_t version)
|
||||||
{
|
{
|
||||||
if (_handler)
|
if (_handler)
|
||||||
_handler->migrate(settings, version, _codec, _context);
|
_handler->migrate(this->_factory, this, settings, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ffmpeg_instance::update(obs_data_t* settings)
|
bool ffmpeg_instance::update(obs_data_t* settings)
|
||||||
|
@ -199,7 +180,7 @@ bool ffmpeg_instance::update(obs_data_t* settings)
|
||||||
bool support_reconfig_gpu = false;
|
bool support_reconfig_gpu = false;
|
||||||
bool support_reconfig_keyframes = false;
|
bool support_reconfig_keyframes = false;
|
||||||
if (_handler) {
|
if (_handler) {
|
||||||
support_reconfig = _handler->supports_reconfigure(_factory, support_reconfig_threads, support_reconfig_gpu, support_reconfig_keyframes);
|
support_reconfig = _handler->is_reconfigurable(_factory, support_reconfig_threads, support_reconfig_gpu, support_reconfig_keyframes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_context->internal) {
|
if (!_context->internal) {
|
||||||
|
@ -245,7 +226,7 @@ bool ffmpeg_instance::update(obs_data_t* settings)
|
||||||
|
|
||||||
if (!_context->internal || (support_reconfig && support_reconfig_keyframes)) {
|
if (!_context->internal || (support_reconfig && support_reconfig_keyframes)) {
|
||||||
// Keyframes
|
// Keyframes
|
||||||
if (_handler && _handler->has_keyframe_support(_factory)) {
|
if (_handler && _handler->has_keyframes(_factory)) {
|
||||||
// Key-Frame Options
|
// Key-Frame Options
|
||||||
obs_video_info ovi;
|
obs_video_info ovi;
|
||||||
if (!obs_get_video_info(&ovi)) {
|
if (!obs_get_video_info(&ovi)) {
|
||||||
|
@ -268,7 +249,7 @@ bool ffmpeg_instance::update(obs_data_t* settings)
|
||||||
if (!_context->internal || support_reconfig) {
|
if (!_context->internal || support_reconfig) {
|
||||||
// Handler Options
|
// Handler Options
|
||||||
if (_handler)
|
if (_handler)
|
||||||
_handler->update(settings, _codec, _context);
|
_handler->update(this->_factory, this, settings);
|
||||||
|
|
||||||
{ // FFmpeg Custom Options
|
{ // FFmpeg Custom Options
|
||||||
const char* opts = obs_data_get_string(settings, ST_KEY_FFMPEG_CUSTOMSETTINGS);
|
const char* opts = obs_data_get_string(settings, ST_KEY_FFMPEG_CUSTOMSETTINGS);
|
||||||
|
@ -279,7 +260,7 @@ bool ffmpeg_instance::update(obs_data_t* settings)
|
||||||
|
|
||||||
// Handler Overrides
|
// Handler Overrides
|
||||||
if (_handler)
|
if (_handler)
|
||||||
_handler->override_update(this, settings);
|
_handler->override_update(this->_factory, this, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler Logging
|
// Handler Logging
|
||||||
|
@ -310,7 +291,7 @@ bool ffmpeg_instance::update(obs_data_t* settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_handler) {
|
if (_handler) {
|
||||||
_handler->log_options(settings, _codec, _context);
|
_handler->log(this->_factory, this, settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,7 +419,7 @@ void ffmpeg_instance::initialize_sw(obs_data_t* settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_handler) // Allow Handler to override the automatic color format for sanity reasons.
|
if (_handler) // Allow Handler to override the automatic color format for sanity reasons.
|
||||||
_handler->override_colorformat(pix_fmt_target, settings, _codec, _context);
|
_handler->override_colorformat(this->_factory, this, settings, pix_fmt_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup from OBS information.
|
// Setup from OBS information.
|
||||||
|
@ -634,8 +615,9 @@ int ffmpeg_instance::receive_packet(bool* received_packet, struct encoder_packet
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow Handler Post-Processing
|
// Allow Handler Post-Processing
|
||||||
if (_handler)
|
//FIXME! Is this still necessary?
|
||||||
_handler->process_avpacket(_packet, _codec, _context);
|
//if (_handler)
|
||||||
|
// _handler->process_avpacket(_packet, _codec, _context);
|
||||||
|
|
||||||
// Build packet for use in OBS.
|
// Build packet for use in OBS.
|
||||||
packet->type = OBS_ENCODER_VIDEO;
|
packet->type = OBS_ENCODER_VIDEO;
|
||||||
|
@ -960,10 +942,10 @@ ffmpeg_factory::ffmpeg_factory(ffmpeg_manager* manager, const AVCodec* codec) :
|
||||||
// Find any available handlers for this codec.
|
// Find any available handlers for this codec.
|
||||||
if (_handler = manager->get_handler(_avcodec->name); _handler) {
|
if (_handler = manager->get_handler(_avcodec->name); _handler) {
|
||||||
// Override any found info with the one specified by the handler.
|
// Override any found info with the one specified by the handler.
|
||||||
_handler->adjust_info(this, _avcodec, _id, _name, _codec);
|
_handler->adjust_info(this, _id, _name, _codec);
|
||||||
|
|
||||||
// Add texture capability for hardware encoders.
|
// Add texture capability for hardware encoders.
|
||||||
if (_handler->is_hardware_encoder(this)) {
|
if (_handler->is_hardware(this)) {
|
||||||
_info.caps |= OBS_ENCODER_CAP_PASS_TEXTURE;
|
_info.caps |= OBS_ENCODER_CAP_PASS_TEXTURE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1007,9 +989,9 @@ const char* ffmpeg_factory::get_name()
|
||||||
void ffmpeg_factory::get_defaults2(obs_data_t* settings)
|
void ffmpeg_factory::get_defaults2(obs_data_t* settings)
|
||||||
{
|
{
|
||||||
if (_handler) {
|
if (_handler) {
|
||||||
_handler->get_defaults(settings, _avcodec, nullptr, _handler->is_hardware_encoder(this));
|
_handler->defaults(this, settings);
|
||||||
|
|
||||||
if (_handler->has_keyframe_support(this)) {
|
if (_handler->has_keyframes(this)) {
|
||||||
obs_data_set_default_int(settings, ST_KEY_KEYFRAMES_INTERVALTYPE, 0);
|
obs_data_set_default_int(settings, ST_KEY_KEYFRAMES_INTERVALTYPE, 0);
|
||||||
obs_data_set_default_double(settings, ST_KEY_KEYFRAMES_INTERVAL_SECONDS, 2.0);
|
obs_data_set_default_double(settings, ST_KEY_KEYFRAMES_INTERVAL_SECONDS, 2.0);
|
||||||
obs_data_set_default_int(settings, ST_KEY_KEYFRAMES_INTERVAL_FRAMES, 300);
|
obs_data_set_default_int(settings, ST_KEY_KEYFRAMES_INTERVAL_FRAMES, 300);
|
||||||
|
@ -1027,7 +1009,7 @@ void ffmpeg_factory::get_defaults2(obs_data_t* settings)
|
||||||
void ffmpeg_factory::migrate(obs_data_t* data, uint64_t version)
|
void ffmpeg_factory::migrate(obs_data_t* data, uint64_t version)
|
||||||
{
|
{
|
||||||
if (_handler)
|
if (_handler)
|
||||||
_handler->migrate(data, version, _avcodec, nullptr);
|
_handler->migrate(this, nullptr, data, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool modified_keyframes(obs_properties_t* props, obs_property_t*, obs_data_t* settings) noexcept
|
static bool modified_keyframes(obs_properties_t* props, obs_property_t*, obs_data_t* settings) noexcept
|
||||||
|
@ -1061,9 +1043,9 @@ obs_properties_t* ffmpeg_factory::get_properties2(instance_t* data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_handler)
|
if (_handler)
|
||||||
_handler->get_properties(props, _avcodec, nullptr, _handler->is_hardware_encoder(this));
|
_handler->properties(this, data, props);
|
||||||
|
|
||||||
if (_handler && _handler->has_keyframe_support(this)) {
|
if (_handler && _handler->has_keyframes(this)) {
|
||||||
// Key-Frame Options
|
// Key-Frame Options
|
||||||
obs_properties_t* grp = props;
|
obs_properties_t* grp = props;
|
||||||
if (!streamfx::util::are_property_groups_broken()) {
|
if (!streamfx::util::are_property_groups_broken()) {
|
||||||
|
@ -1099,11 +1081,11 @@ obs_properties_t* ffmpeg_factory::get_properties2(instance_t* data)
|
||||||
auto p = obs_properties_add_text(grp, ST_KEY_FFMPEG_CUSTOMSETTINGS, D_TRANSLATE(ST_I18N_FFMPEG_CUSTOMSETTINGS), obs_text_type::OBS_TEXT_DEFAULT);
|
auto p = obs_properties_add_text(grp, ST_KEY_FFMPEG_CUSTOMSETTINGS, D_TRANSLATE(ST_I18N_FFMPEG_CUSTOMSETTINGS), obs_text_type::OBS_TEXT_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_handler && _handler->is_hardware_encoder(this)) {
|
if (_handler && _handler->is_hardware(this)) {
|
||||||
auto p = obs_properties_add_int(grp, ST_KEY_FFMPEG_GPU, D_TRANSLATE(ST_I18N_FFMPEG_GPU), -1, std::numeric_limits<uint8_t>::max(), 1);
|
auto p = obs_properties_add_int(grp, ST_KEY_FFMPEG_GPU, D_TRANSLATE(ST_I18N_FFMPEG_GPU), -1, std::numeric_limits<uint8_t>::max(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_handler && _handler->has_threading_support(this)) {
|
if (_handler && _handler->has_threading(this)) {
|
||||||
auto p = obs_properties_add_int_slider(grp, ST_KEY_FFMPEG_THREADS, D_TRANSLATE(ST_I18N_FFMPEG_THREADS), 0, static_cast<int64_t>(std::thread::hardware_concurrency()) * 2, 1);
|
auto p = obs_properties_add_int_slider(grp, ST_KEY_FFMPEG_THREADS, D_TRANSLATE(ST_I18N_FFMPEG_THREADS), 0, static_cast<int64_t>(std::thread::hardware_concurrency()) * 2, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1132,7 +1114,7 @@ obs_properties_t* ffmpeg_factory::get_properties2(instance_t* data)
|
||||||
bool ffmpeg_factory::on_manual_open(obs_properties_t* props, obs_property_t* property, void* data)
|
bool ffmpeg_factory::on_manual_open(obs_properties_t* props, obs_property_t* property, void* data)
|
||||||
{
|
{
|
||||||
ffmpeg_factory* ptr = static_cast<ffmpeg_factory*>(data);
|
ffmpeg_factory* ptr = static_cast<ffmpeg_factory*>(data);
|
||||||
streamfx::open_url(ptr->_handler->get_help_url(ptr->_avcodec));
|
streamfx::open_url(ptr->_handler->help(ptr));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1147,25 +1129,8 @@ obs_encoder_info* streamfx::encoder::ffmpeg::ffmpeg_factory::get_info()
|
||||||
return &_info;
|
return &_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
ffmpeg_manager::ffmpeg_manager() : _factories(), _handlers(), _debug_handler()
|
ffmpeg_manager::ffmpeg_manager() : _factories()
|
||||||
{
|
{
|
||||||
// Handlers
|
|
||||||
_debug_handler = ::std::make_shared<handler::debug_handler>();
|
|
||||||
#ifdef ENABLE_ENCODER_FFMPEG_AMF
|
|
||||||
register_handler("h264_amf", ::std::make_shared<handler::amf_h264_handler>());
|
|
||||||
register_handler("hevc_amf", ::std::make_shared<handler::amf_hevc_handler>());
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_ENCODER_FFMPEG_NVENC
|
|
||||||
register_handler("h264_nvenc", ::std::make_shared<handler::nvenc_h264_handler>());
|
|
||||||
register_handler("hevc_nvenc", ::std::make_shared<handler::nvenc_hevc_handler>());
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_ENCODER_FFMPEG_PRORES
|
|
||||||
register_handler("prores_aw", ::std::make_shared<handler::prores_aw_handler>());
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_ENCODER_FFMPEG_DNXHR
|
|
||||||
register_handler("dnxhd", ::std::make_shared<handler::dnxhd_handler>());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Encoders
|
// Encoders
|
||||||
void* iterator = nullptr;
|
void* iterator = nullptr;
|
||||||
for (const AVCodec* codec = av_codec_iterate(&iterator); codec != nullptr; codec = av_codec_iterate(&iterator)) {
|
for (const AVCodec* codec = av_codec_iterate(&iterator); codec != nullptr; codec = av_codec_iterate(&iterator)) {
|
||||||
|
@ -1188,28 +1153,6 @@ ffmpeg_manager::~ffmpeg_manager()
|
||||||
_factories.clear();
|
_factories.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg_manager::register_handler(std::string codec, std::shared_ptr<handler::handler> handler)
|
|
||||||
{
|
|
||||||
_handlers.emplace(codec, handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<handler::handler> ffmpeg_manager::get_handler(std::string codec)
|
|
||||||
{
|
|
||||||
auto fnd = _handlers.find(codec);
|
|
||||||
if (fnd != _handlers.end())
|
|
||||||
return fnd->second;
|
|
||||||
#ifdef _DEBUG
|
|
||||||
return _debug_handler;
|
|
||||||
#else
|
|
||||||
return nullptr;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ffmpeg_manager::has_handler(std::string_view codec)
|
|
||||||
{
|
|
||||||
return (_handlers.find(codec.data()) != _handlers.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<ffmpeg_manager> ffmpeg_manager::instance()
|
std::shared_ptr<ffmpeg_manager> ffmpeg_manager::instance()
|
||||||
{
|
{
|
||||||
static std::weak_ptr<ffmpeg_manager> winst;
|
static std::weak_ptr<ffmpeg_manager> winst;
|
||||||
|
@ -1224,6 +1167,30 @@ std::shared_ptr<ffmpeg_manager> ffmpeg_manager::instance()
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
streamfx::encoder::ffmpeg::handler* ffmpeg_manager::find_handler(std::string_view codec)
|
||||||
|
{
|
||||||
|
auto handlers = streamfx::encoder::ffmpeg::handler::handlers();
|
||||||
|
if (auto kv = handlers.find(std::string{codec}); kv != handlers.end()) {
|
||||||
|
return kv->second;
|
||||||
|
}
|
||||||
|
#ifdef _DEBUG
|
||||||
|
if (auto kv = handlers.find(""); kv != handlers.end()) {
|
||||||
|
return kv->second;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
streamfx::encoder::ffmpeg::handler* ffmpeg_manager::get_handler(std::string_view codec)
|
||||||
|
{
|
||||||
|
return find_handler(codec);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ffmpeg_manager::has_handler(std::string_view codec)
|
||||||
|
{
|
||||||
|
return find_handler(codec) != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
static std::shared_ptr<ffmpeg_manager> loader_instance;
|
static std::shared_ptr<ffmpeg_manager> loader_instance;
|
||||||
|
|
||||||
static auto loader = streamfx::loader(
|
static auto loader = streamfx::loader(
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
|
#include "encoders/ffmpeg/handler.hpp"
|
||||||
#include "ffmpeg/avframe-queue.hpp"
|
#include "ffmpeg/avframe-queue.hpp"
|
||||||
#include "ffmpeg/hwapi/base.hpp"
|
#include "ffmpeg/hwapi/base.hpp"
|
||||||
#include "ffmpeg/swscale.hpp"
|
#include "ffmpeg/swscale.hpp"
|
||||||
#include "handlers/handler.hpp"
|
|
||||||
#include "obs/obs-encoder-factory.hpp"
|
#include "obs/obs-encoder-factory.hpp"
|
||||||
|
|
||||||
#include "warning-disable.hpp"
|
#include "warning-disable.hpp"
|
||||||
|
@ -17,16 +17,15 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "warning-enable.hpp"
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "warning-disable.hpp"
|
|
||||||
#include <libavcodec/avcodec.h>
|
#include <libavcodec/avcodec.h>
|
||||||
#include <libavutil/frame.h>
|
#include <libavutil/frame.h>
|
||||||
#include "warning-enable.hpp"
|
|
||||||
}
|
}
|
||||||
|
#include "warning-enable.hpp"
|
||||||
|
|
||||||
namespace streamfx::encoder::ffmpeg {
|
namespace streamfx::encoder::ffmpeg {
|
||||||
class ffmpeg_instance;
|
class ffmpeg_instance;
|
||||||
|
@ -38,7 +37,7 @@ namespace streamfx::encoder::ffmpeg {
|
||||||
const AVCodec* _codec;
|
const AVCodec* _codec;
|
||||||
AVCodecContext* _context;
|
AVCodecContext* _context;
|
||||||
|
|
||||||
std::shared_ptr<handler::handler> _handler;
|
streamfx::encoder::ffmpeg::handler* _handler;
|
||||||
|
|
||||||
::streamfx::ffmpeg::swscale _scaler;
|
::streamfx::ffmpeg::swscale _scaler;
|
||||||
std::shared_ptr<AVPacket> _packet;
|
std::shared_ptr<AVPacket> _packet;
|
||||||
|
@ -116,7 +115,7 @@ namespace streamfx::encoder::ffmpeg {
|
||||||
|
|
||||||
const AVCodec* _avcodec;
|
const AVCodec* _avcodec;
|
||||||
|
|
||||||
std::shared_ptr<handler::handler> _handler;
|
streamfx::encoder::ffmpeg::handler* _handler;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ffmpeg_factory(ffmpeg_manager* manager, const AVCodec* codec);
|
ffmpeg_factory(ffmpeg_manager* manager, const AVCodec* codec);
|
||||||
|
@ -142,16 +141,14 @@ namespace streamfx::encoder::ffmpeg {
|
||||||
|
|
||||||
class ffmpeg_manager {
|
class ffmpeg_manager {
|
||||||
std::map<const AVCodec*, std::shared_ptr<ffmpeg_factory>> _factories;
|
std::map<const AVCodec*, std::shared_ptr<ffmpeg_factory>> _factories;
|
||||||
std::map<std::string, std::shared_ptr<handler::handler>> _handlers;
|
|
||||||
std::shared_ptr<handler::handler> _debug_handler;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ffmpeg_manager();
|
ffmpeg_manager();
|
||||||
~ffmpeg_manager();
|
~ffmpeg_manager();
|
||||||
|
|
||||||
void register_handler(std::string codec, std::shared_ptr<handler::handler> handler);
|
streamfx::encoder::ffmpeg::handler* find_handler(std::string_view codec);
|
||||||
|
|
||||||
std::shared_ptr<handler::handler> get_handler(std::string codec);
|
streamfx::encoder::ffmpeg::handler* get_handler(std::string_view codec);
|
||||||
|
|
||||||
bool has_handler(std::string_view codec);
|
bool has_handler(std::string_view codec);
|
||||||
|
|
||||||
|
|
|
@ -1,41 +1,67 @@
|
||||||
// AUTOGENERATED COPYRIGHT HEADER START
|
|
||||||
// Copyright (C) 2020-2023 Michael Fabian 'Xaymar' Dirks <info@xaymar.com>
|
|
||||||
// AUTOGENERATED COPYRIGHT HEADER END
|
|
||||||
|
|
||||||
#include "handler.hpp"
|
#include "handler.hpp"
|
||||||
#include "../encoder-ffmpeg.hpp"
|
#include "../encoder-ffmpeg.hpp"
|
||||||
|
|
||||||
using namespace streamfx::encoder::ffmpeg;
|
streamfx::encoder::ffmpeg::handler::handler_map_t& streamfx::encoder::ffmpeg::handler::handlers()
|
||||||
|
{
|
||||||
|
static handler_map_t handlers;
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
bool handler::handler::has_keyframe_support(ffmpeg_factory* instance)
|
streamfx::encoder::ffmpeg::handler::handler(std::string codec)
|
||||||
|
{
|
||||||
|
handlers().emplace(codec, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool streamfx::encoder::ffmpeg::handler::has_keyframes(ffmpeg_factory* factory)
|
||||||
{
|
{
|
||||||
#if LIBAVCODEC_VERSION_MAJOR > 58
|
#if LIBAVCODEC_VERSION_MAJOR > 58
|
||||||
if (auto* desc = avcodec_descriptor_get(instance->get_avcodec()->id); desc) {
|
if (auto* desc = avcodec_descriptor_get(factory->get_avcodec()->id); desc) {
|
||||||
return (desc->props & AV_CODEC_PROP_INTRA_ONLY) == 0;
|
return (desc->props & AV_CODEC_PROP_INTRA_ONLY) == 0;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
return (instance->get_avcodec()->capabilities & AV_CODEC_CAP_INTRA_ONLY) == 0;
|
return (factory->get_avcodec()->capabilities & AV_CODEC_CAP_INTRA_ONLY) == 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool handler::handler::is_hardware_encoder(ffmpeg_factory* instance)
|
bool streamfx::encoder::ffmpeg::handler::has_threading(ffmpeg_factory* factory)
|
||||||
{
|
{
|
||||||
|
return (factory->get_avcodec()->capabilities & (AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_OTHER_THREADS));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool streamfx::encoder::ffmpeg::handler::is_hardware(ffmpeg_factory* factory)
|
||||||
|
{
|
||||||
|
if (factory->get_avcodec()->capabilities & AV_CODEC_CAP_HARDWARE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool handler::handler::has_threading_support(ffmpeg_factory* instance)
|
bool streamfx::encoder::ffmpeg::handler::is_reconfigurable(ffmpeg_factory* factory, bool& threads, bool& gpu, bool& keyframes)
|
||||||
{
|
|
||||||
return (instance->get_avcodec()->capabilities & (AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool handler::handler::has_pixel_format_support(ffmpeg_factory* instance)
|
|
||||||
{
|
|
||||||
return (instance->get_avcodec()->pix_fmts != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool handler::handler::supports_reconfigure(ffmpeg_factory* instance, bool& threads, bool& gpu, bool& keyframes)
|
|
||||||
{
|
{
|
||||||
|
if (factory->get_avcodec()->capabilities & AV_CODEC_CAP_PARAM_CHANGE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void streamfx::encoder::ffmpeg::handler::adjust_info(ffmpeg_factory* factory, std::string& id, std::string& name, std::string& codec) {}
|
||||||
|
|
||||||
|
std::string streamfx::encoder::ffmpeg::handler::help(ffmpeg_factory* factory) {
|
||||||
|
return "about:blank";
|
||||||
|
}
|
||||||
|
|
||||||
|
void streamfx::encoder::ffmpeg::handler::defaults(ffmpeg_factory* factory, obs_data_t* settings) {}
|
||||||
|
|
||||||
|
void streamfx::encoder::ffmpeg::handler::properties(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_properties_t* props) {}
|
||||||
|
|
||||||
|
void streamfx::encoder::ffmpeg::handler::migrate(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_data_t* settings, uint64_t version) {}
|
||||||
|
|
||||||
|
void streamfx::encoder::ffmpeg::handler::update(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_data_t* settings) {}
|
||||||
|
|
||||||
|
void streamfx::encoder::ffmpeg::handler::override_update(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_data_t* settings) {}
|
||||||
|
|
||||||
|
void streamfx::encoder::ffmpeg::handler::log(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_data_t* settings) {}
|
||||||
|
|
||||||
|
void streamfx::encoder::ffmpeg::handler::override_colorformat(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_data_t* settings, AVPixelFormat target_format) {}
|
||||||
|
|
|
@ -1,63 +1,42 @@
|
||||||
// AUTOGENERATED COPYRIGHT HEADER START
|
|
||||||
// Copyright (C) 2020-2023 Michael Fabian 'Xaymar' Dirks <info@xaymar.com>
|
|
||||||
// AUTOGENERATED COPYRIGHT HEADER END
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "common.hpp"
|
|
||||||
#include "ffmpeg/hwapi/base.hpp"
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include "warning-disable.hpp"
|
#include "warning-disable.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
extern "C" {
|
||||||
|
#include <obs.h>
|
||||||
#include <libavcodec/avcodec.h>
|
#include <libavcodec/avcodec.h>
|
||||||
#include "warning-enable.hpp"
|
|
||||||
}
|
}
|
||||||
|
#include "warning-enable.hpp"
|
||||||
|
|
||||||
namespace streamfx::encoder::ffmpeg {
|
namespace streamfx::encoder::ffmpeg {
|
||||||
struct ffmpeg_info;
|
|
||||||
class ffmpeg_factory;
|
class ffmpeg_factory;
|
||||||
class ffmpeg_instance;
|
class ffmpeg_instance;
|
||||||
|
|
||||||
namespace handler {
|
struct handler {
|
||||||
class handler {
|
handler(std::string codec);
|
||||||
public:
|
|
||||||
virtual ~handler(){};
|
|
||||||
|
|
||||||
public /*factory*/:
|
virtual bool has_keyframes(ffmpeg_factory* factory);
|
||||||
virtual void adjust_info(ffmpeg_factory* factory, const AVCodec* codec, std::string& id, std::string& name, std::string& codec_id){};
|
virtual bool has_threading(ffmpeg_factory* factory);
|
||||||
|
virtual bool is_hardware(ffmpeg_factory* factory);
|
||||||
|
virtual bool is_reconfigurable(ffmpeg_factory* factory, bool& threads, bool& gpu, bool& keyframes);
|
||||||
|
|
||||||
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, bool hw_encode){};
|
virtual void adjust_info(ffmpeg_factory* factory, std::string& id, std::string& name, std::string& codec);
|
||||||
|
|
||||||
virtual std::string_view get_help_url(const AVCodec* codec)
|
virtual std::string help(ffmpeg_factory* factory);
|
||||||
{
|
|
||||||
return "https://github.com/Xaymar/obs-StreamFX/wiki/Encoder-FFmpeg";
|
|
||||||
};
|
|
||||||
|
|
||||||
public /*support tests*/:
|
virtual void defaults(ffmpeg_factory* factory, obs_data_t* settings);
|
||||||
virtual bool has_keyframe_support(ffmpeg_factory* instance);
|
virtual void properties(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_properties_t* props);
|
||||||
|
virtual void migrate(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_data_t* settings, uint64_t version);
|
||||||
|
virtual void update(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_data_t* settings);
|
||||||
|
virtual void override_update(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_data_t* settings);
|
||||||
|
virtual void log(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_data_t* settings);
|
||||||
|
|
||||||
virtual bool is_hardware_encoder(ffmpeg_factory* instance);
|
virtual void override_colorformat(ffmpeg_factory* factory, ffmpeg_instance* instance, obs_data_t* settings, AVPixelFormat target_format);
|
||||||
|
|
||||||
virtual bool has_threading_support(ffmpeg_factory* instance);
|
public:
|
||||||
|
typedef std::map<std::string, handler*> handler_map_t;
|
||||||
|
|
||||||
virtual bool has_pixel_format_support(ffmpeg_factory* instance);
|
static handler_map_t& handlers();
|
||||||
|
};
|
||||||
virtual bool supports_reconfigure(ffmpeg_factory* instance, bool& threads, bool& gpu, bool& keyframes);
|
|
||||||
|
|
||||||
public /*settings*/:
|
|
||||||
virtual void get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context, bool hw_encode){};
|
|
||||||
|
|
||||||
virtual void migrate(obs_data_t* settings, uint64_t version, const AVCodec* codec, AVCodecContext* context){};
|
|
||||||
|
|
||||||
virtual void update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context){};
|
|
||||||
|
|
||||||
virtual void override_update(ffmpeg_instance* instance, obs_data_t* settings){};
|
|
||||||
|
|
||||||
virtual void log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context){};
|
|
||||||
|
|
||||||
public /*instance*/:
|
|
||||||
virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings, const AVCodec* codec, AVCodecContext* context){};
|
|
||||||
|
|
||||||
virtual void process_avpacket(std::shared_ptr<AVPacket> packet, const AVCodec* codec, AVCodecContext* context){};
|
|
||||||
};
|
|
||||||
} // namespace handler
|
|
||||||
} // namespace streamfx::encoder::ffmpeg
|
} // namespace streamfx::encoder::ffmpeg
|
||||||
|
|
Loading…
Reference in New Issue