mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-11-14 07:45:06 +00:00
encoders/ffmpeg: Add support for re-configuration of encoders
This commit is contained in:
parent
977716d679
commit
19689d1a11
3 changed files with 90 additions and 60 deletions
|
@ -191,78 +191,98 @@ void ffmpeg_instance::migrate(obs_data_t* settings, uint64_t version)
|
||||||
|
|
||||||
bool ffmpeg_instance::update(obs_data_t* settings)
|
bool ffmpeg_instance::update(obs_data_t* settings)
|
||||||
{
|
{
|
||||||
// FFmpeg Options
|
bool support_reconfig = false;
|
||||||
_context->debug = 0;
|
bool support_reconfig_threads = false;
|
||||||
_context->strict_std_compliance = FF_COMPLIANCE_NORMAL;
|
bool support_reconfig_gpu = false;
|
||||||
|
bool support_reconfig_keyframes = false;
|
||||||
|
if (_handler) {
|
||||||
|
support_reconfig = _handler->supports_reconfigure(_factory, support_reconfig_threads, support_reconfig_gpu,
|
||||||
|
support_reconfig_keyframes);
|
||||||
|
}
|
||||||
|
|
||||||
/// Threading
|
if (!_context->internal) {
|
||||||
if (!_hwinst) {
|
// FFmpeg Options
|
||||||
_context->thread_type = 0;
|
_context->debug = 0;
|
||||||
if (_codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) {
|
_context->strict_std_compliance = FF_COMPLIANCE_NORMAL;
|
||||||
_context->thread_type |= FF_THREAD_FRAME;
|
}
|
||||||
}
|
|
||||||
if (_codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) {
|
if (!_context->internal || (support_reconfig && support_reconfig_threads)) {
|
||||||
_context->thread_type |= FF_THREAD_SLICE;
|
/// Threading
|
||||||
}
|
if (!_hwinst) {
|
||||||
if (_context->thread_type != 0) {
|
_context->thread_type = 0;
|
||||||
int64_t threads = obs_data_get_int(settings, ST_I18N_FFMPEG_THREADS);
|
if (_codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) {
|
||||||
if (threads > 0) {
|
_context->thread_type |= FF_THREAD_FRAME;
|
||||||
_context->thread_count = static_cast<int>(threads);
|
|
||||||
} else {
|
|
||||||
_context->thread_count = static_cast<int>(std::thread::hardware_concurrency());
|
|
||||||
}
|
}
|
||||||
|
if (_codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) {
|
||||||
|
_context->thread_type |= FF_THREAD_SLICE;
|
||||||
|
}
|
||||||
|
if (_context->thread_type != 0) {
|
||||||
|
int64_t threads = obs_data_get_int(settings, ST_I18N_FFMPEG_THREADS);
|
||||||
|
if (threads > 0) {
|
||||||
|
_context->thread_count = static_cast<int>(threads);
|
||||||
|
} else {
|
||||||
|
_context->thread_count = static_cast<int>(std::thread::hardware_concurrency());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_context->thread_count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frame Delay (Lag In Frames)
|
||||||
|
_context->delay = _context->thread_count;
|
||||||
} else {
|
} else {
|
||||||
_context->thread_count = 1;
|
_context->delay = 0;
|
||||||
}
|
}
|
||||||
// Frame Delay (Lag In Frames)
|
|
||||||
_context->delay = _context->thread_count;
|
|
||||||
} else {
|
|
||||||
_context->delay = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply GPU Selection
|
if (!_context->internal || (support_reconfig && support_reconfig_gpu)) {
|
||||||
if (!_hwinst && ::streamfx::ffmpeg::tools::can_hardware_encode(_codec)) {
|
// Apply GPU Selection
|
||||||
av_opt_set_int(_context, "gpu", (int)obs_data_get_int(settings, ST_KEY_FFMPEG_GPU), AV_OPT_SEARCH_CHILDREN);
|
if (!_hwinst && ::streamfx::ffmpeg::tools::can_hardware_encode(_codec)) {
|
||||||
|
av_opt_set_int(_context, "gpu", (int)obs_data_get_int(settings, ST_KEY_FFMPEG_GPU), AV_OPT_SEARCH_CHILDREN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keyframes
|
if (!_context->internal || (support_reconfig && support_reconfig_keyframes)) {
|
||||||
if (_handler && _handler->has_keyframe_support(_factory)) {
|
// Keyframes
|
||||||
// Key-Frame Options
|
if (_handler && _handler->has_keyframe_support(_factory)) {
|
||||||
obs_video_info ovi;
|
// Key-Frame Options
|
||||||
if (!obs_get_video_info(&ovi)) {
|
obs_video_info ovi;
|
||||||
throw std::runtime_error("obs_get_video_info failed, restart OBS Studio to fix it (hopefully).");
|
if (!obs_get_video_info(&ovi)) {
|
||||||
|
throw std::runtime_error("obs_get_video_info failed, restart OBS Studio to fix it (hopefully).");
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t kf_type = obs_data_get_int(settings, ST_KEY_KEYFRAMES_INTERVALTYPE);
|
||||||
|
bool is_seconds = (kf_type == 0);
|
||||||
|
|
||||||
|
if (is_seconds) {
|
||||||
|
_context->gop_size = static_cast<int>(obs_data_get_double(settings, ST_KEY_KEYFRAMES_INTERVAL_SECONDS)
|
||||||
|
* (ovi.fps_num / ovi.fps_den));
|
||||||
|
} else {
|
||||||
|
_context->gop_size = static_cast<int>(obs_data_get_int(settings, ST_KEY_KEYFRAMES_INTERVAL_FRAMES));
|
||||||
|
}
|
||||||
|
_context->keyint_min = _context->gop_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_context->internal || support_reconfig) {
|
||||||
|
// Handler Options
|
||||||
|
if (_handler)
|
||||||
|
_handler->update(settings, _codec, _context);
|
||||||
|
|
||||||
|
{ // FFmpeg Custom Options
|
||||||
|
const char* opts = obs_data_get_string(settings, ST_KEY_FFMPEG_CUSTOMSETTINGS);
|
||||||
|
std::size_t opts_len = strnlen(opts, 65535);
|
||||||
|
|
||||||
|
parse_ffmpeg_commandline(std::string{opts, opts + opts_len});
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t kf_type = obs_data_get_int(settings, ST_KEY_KEYFRAMES_INTERVALTYPE);
|
// Handler Overrides
|
||||||
bool is_seconds = (kf_type == 0);
|
if (_handler)
|
||||||
|
_handler->override_update(this, settings);
|
||||||
if (is_seconds) {
|
|
||||||
_context->gop_size = static_cast<int>(obs_data_get_double(settings, ST_KEY_KEYFRAMES_INTERVAL_SECONDS)
|
|
||||||
* (ovi.fps_num / ovi.fps_den));
|
|
||||||
} else {
|
|
||||||
_context->gop_size = static_cast<int>(obs_data_get_int(settings, ST_KEY_KEYFRAMES_INTERVAL_FRAMES));
|
|
||||||
}
|
|
||||||
_context->keyint_min = _context->gop_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler Options
|
|
||||||
if (_handler)
|
|
||||||
_handler->update(settings, _codec, _context);
|
|
||||||
|
|
||||||
{ // FFmpeg Custom Options
|
|
||||||
const char* opts = obs_data_get_string(settings, ST_KEY_FFMPEG_CUSTOMSETTINGS);
|
|
||||||
std::size_t opts_len = strnlen(opts, 65535);
|
|
||||||
|
|
||||||
parse_ffmpeg_commandline(std::string{opts, opts + opts_len});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handler Overrides
|
|
||||||
if (_handler)
|
|
||||||
_handler->override_update(this, settings);
|
|
||||||
|
|
||||||
// Handler Logging
|
// Handler Logging
|
||||||
if (_handler) {
|
if (!_context->internal || support_reconfig) {
|
||||||
DLOG_INFO("[%s] Initializing...", _codec->name);
|
DLOG_INFO("[%s] Configuration:", _codec->name);
|
||||||
DLOG_INFO("[%s] FFmpeg:", _codec->name);
|
DLOG_INFO("[%s] FFmpeg:", _codec->name);
|
||||||
DLOG_INFO("[%s] Custom Settings: %s", _codec->name,
|
DLOG_INFO("[%s] Custom Settings: %s", _codec->name,
|
||||||
obs_data_get_string(settings, ST_KEY_FFMPEG_CUSTOMSETTINGS));
|
obs_data_get_string(settings, ST_KEY_FFMPEG_CUSTOMSETTINGS));
|
||||||
|
@ -302,7 +322,10 @@ bool ffmpeg_instance::update(obs_data_t* settings)
|
||||||
} else {
|
} else {
|
||||||
DLOG_INFO("[%s] Distance: %i frames", _codec->name, _context->gop_size);
|
DLOG_INFO("[%s] Distance: %i frames", _codec->name, _context->gop_size);
|
||||||
}
|
}
|
||||||
_handler->log_options(settings, _codec, _context);
|
|
||||||
|
if (_handler) {
|
||||||
|
_handler->log_options(settings, _codec, _context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -43,3 +43,8 @@ bool handler::handler::has_pixel_format_support(ffmpeg_factory* instance)
|
||||||
{
|
{
|
||||||
return (instance->get_avcodec()->pix_fmts != nullptr);
|
return (instance->get_avcodec()->pix_fmts != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool handler::handler::supports_reconfigure(ffmpeg_factory* instance, bool& threads, bool& gpu, bool& keyframes)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -61,6 +61,8 @@ namespace streamfx::encoder::ffmpeg {
|
||||||
|
|
||||||
virtual bool has_pixel_format_support(ffmpeg_factory* instance);
|
virtual bool has_pixel_format_support(ffmpeg_factory* instance);
|
||||||
|
|
||||||
|
virtual bool supports_reconfigure(ffmpeg_factory* instance, bool& threads, bool& gpu, bool& keyframes);
|
||||||
|
|
||||||
public /*settings*/:
|
public /*settings*/:
|
||||||
virtual void get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context,
|
virtual void get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context,
|
||||||
bool hw_encode){};
|
bool hw_encode){};
|
||||||
|
|
Loading…
Reference in a new issue