diff --git a/source/encoder.cpp b/source/encoder.cpp index f7c5597..5363a19 100644 --- a/source/encoder.cpp +++ b/source/encoder.cpp @@ -355,10 +355,6 @@ obsffmpeg::encoder_factory::encoder_factory(const AVCodec* codec) : avcodec_ptr( sstr << " (" << avcodec_ptr->name << ")"; } info.readable_name = sstr.str(); - - // Allow UI Handler to replace visible name. - if (_handler) - _handler->get_name(avcodec_ptr, info.readable_name); } // Assign Ids. @@ -812,34 +808,6 @@ obsffmpeg::encoder::encoder(obs_data_t* settings, obs_encoder_t* encoder, bool i initialize_sw(settings); } - // Log Encoder info - PLOG_INFO("[%s] Initializing...", _codec->name); - if (_hwinst) { - PLOG_INFO("[%s] Video Input: %ldx%ld %s %s %s", _codec->name, _context->width, _context->height, - ffmpeg::tools::get_pixel_format_name(_context->sw_pix_fmt), - ffmpeg::tools::get_color_space_name(_context->colorspace), - _swscale.is_source_full_range() ? "Full" : "Partial"); - PLOG_INFO("[%s] Video Output: %ldx%ld %s %s %s", _codec->name, _context->width, _context->height, - ffmpeg::tools::get_pixel_format_name(_context->sw_pix_fmt), - ffmpeg::tools::get_color_space_name(_context->colorspace), - _swscale.is_target_full_range() ? "Full" : "Partial"); - } else { - PLOG_INFO("[%s] Video Input: %ldx%ld %s %s %s", _codec->name, _swscale.get_source_width(), - _swscale.get_source_height(), - ffmpeg::tools::get_pixel_format_name(_swscale.get_source_format()), - ffmpeg::tools::get_color_space_name(_swscale.get_source_colorspace()), - _swscale.is_source_full_range() ? "Full" : "Partial"); - PLOG_INFO("[%s] Video Output: %ldx%ld %s %s %s", _codec->name, _swscale.get_target_width(), - _swscale.get_target_height(), - ffmpeg::tools::get_pixel_format_name(_swscale.get_target_format()), - ffmpeg::tools::get_color_space_name(_swscale.get_target_colorspace()), - _swscale.is_target_full_range() ? "Full" : "Partial"); - PLOG_INFO("[%s] GPU Selected: %d", _codec->name, obs_data_get_int(settings, ST_FFMPEG_GPU)); - } - PLOG_INFO("[%s] Framerate: %ld/%ld (%f FPS)", _codec->name, _context->time_base.den, _context->time_base.num, - static_cast(_context->time_base.den) / static_cast(_context->time_base.num)); - PLOG_INFO("[%s] Custom Settings: %s", _codec->name, obs_data_get_string(settings, ST_FFMPEG_CUSTOMSETTINGS)); - // Update settings update(settings); @@ -895,41 +863,47 @@ void obsffmpeg::encoder::get_properties(obs_properties_t* props, bool hw_encode) bool obsffmpeg::encoder::update(obs_data_t* settings) { - // Settings - /// Rate Control - _context->strict_std_compliance = static_cast(obs_data_get_int(settings, ST_FFMPEG_STANDARDCOMPLIANCE)); + // FFmpeg Options _context->debug = 0; + _context->strict_std_compliance = static_cast(obs_data_get_int(settings, ST_FFMPEG_STANDARDCOMPLIANCE)); + /// Threading - if (_codec->capabilities & (AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS) - && !_hwinst) { + if (!_hwinst) { + _context->thread_type = 0; if (_codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) { _context->thread_type |= FF_THREAD_FRAME; } if (_codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) { _context->thread_type |= FF_THREAD_SLICE; } - int64_t threads = obs_data_get_int(settings, ST_FFMPEG_THREADS); - if (threads > 0) { - _context->thread_count = static_cast(threads); - _lag_in_frames = _context->thread_count; + if (_context->thread_type != 0) { + int64_t threads = obs_data_get_int(settings, ST_FFMPEG_THREADS); + if (threads > 0) { + _context->thread_count = static_cast(threads); + } else { + _context->thread_count = std::thread::hardware_concurrency(); + } } else { - _context->thread_count = std::thread::hardware_concurrency(); - _lag_in_frames = _context->thread_count; + _context->thread_count = 1; } + // Frame Delay (Lag In Frames) + _context->delay = _context->thread_count; } else { - _context->thread_count = 1; - _context->thread_type = 0; - _lag_in_frames = 1; + _context->delay = 0; } - if (_handler) - _handler->update(settings, _codec, _context); + // Apply GPU Selection + if (!_hwinst && ffmpeg::tools::can_hardware_encode(_codec)) { + av_opt_set_int(_context, "gpu", (int)obs_data_get_int(settings, ST_FFMPEG_GPU), AV_OPT_SEARCH_CHILDREN); + } - if ((_codec->capabilities & AV_CODEC_CAP_INTRA_ONLY) == 0) { + // Keyframes + if (_handler && _handler->has_keyframe_support(this)) { // Key-Frame Options obs_video_info ovi; if (!obs_get_video_info(&ovi)) { - throw std::runtime_error("no video info"); + 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, S_KEYFRAMES_INTERVALTYPE); @@ -944,8 +918,9 @@ bool obsffmpeg::encoder::update(obs_data_t* settings) _context->keyint_min = _context->gop_size; } - if (!_hwinst) - av_opt_set_int(_context, "gpu", (int)obs_data_get_int(settings, ST_FFMPEG_GPU), AV_OPT_SEARCH_CHILDREN); + // Handler Options + if (_handler) + _handler->update(settings, _codec, _context); { // FFmpeg Custom Options const char* opts = obs_data_get_string(settings, ST_FFMPEG_CUSTOMSETTINGS); @@ -954,12 +929,56 @@ bool obsffmpeg::encoder::update(obs_data_t* settings) parse_ffmpeg_commandline(std::string{opts, opts + opts_len}); } + // Handler Overrides if (_handler) - _handler->override_lag_in_frames(_lag_in_frames, settings, _codec, _context); + _handler->override_update(this, settings); // Handler Logging - if (_handler) + if (_handler) { + PLOG_INFO("[%s] Initializing...", _codec->name); + PLOG_INFO("[%s] FFmpeg:", _codec->name); + PLOG_INFO("[%s] Custom Settings: %s", _codec->name, + obs_data_get_string(settings, ST_FFMPEG_CUSTOMSETTINGS)); + PLOG_INFO("[%s] Standard Compliance: %s", _codec->name, + ffmpeg::tools::get_std_compliance_name(_context->strict_std_compliance)); + PLOG_INFO("[%s] Threading: %s (with %i threads)", _codec->name, + ffmpeg::tools::get_thread_type_name(_context->thread_type), _context->thread_count); + + PLOG_INFO("[%s] Video:", _codec->name); + if (_hwinst) { + PLOG_INFO("[%s] Texture: %ldx%ld %s %s %s", _codec->name, _context->width, _context->height, + ffmpeg::tools::get_pixel_format_name(_context->sw_pix_fmt), + ffmpeg::tools::get_color_space_name(_context->colorspace), + av_color_range_name(_context->color_range)); + } else { + PLOG_INFO("[%s] Input: %ldx%ld %s %s %s", _codec->name, _swscale.get_source_width(), + _swscale.get_source_height(), + ffmpeg::tools::get_pixel_format_name(_swscale.get_source_format()), + ffmpeg::tools::get_color_space_name(_swscale.get_source_colorspace()), + _swscale.is_source_full_range() ? "Full" : "Partial"); + PLOG_INFO("[%s] Output: %ldx%ld %s %s %s", _codec->name, _swscale.get_target_width(), + _swscale.get_target_height(), + ffmpeg::tools::get_pixel_format_name(_swscale.get_target_format()), + ffmpeg::tools::get_color_space_name(_swscale.get_target_colorspace()), + _swscale.is_target_full_range() ? "Full" : "Partial"); + if (!_hwinst) + PLOG_INFO("[%s] On GPU Index: %lli", _codec->name, + obs_data_get_int(settings, ST_FFMPEG_GPU)); + } + PLOG_INFO("[%s] Framerate: %ld/%ld (%f FPS)", _codec->name, _context->time_base.den, + _context->time_base.num, + static_cast(_context->time_base.den) + / static_cast(_context->time_base.num)); + + PLOG_INFO("[%s] Keyframes: ", _codec->name); + if (_context->keyint_min != _context->gop_size) { + PLOG_INFO("[%s] Minimum: %i frames", _context->keyint_min); + PLOG_INFO("[%s] Maximum: %i frames", _context->gop_size); + } else { + PLOG_INFO("[%s] Distance: %i frames", _context->gop_size); + } _handler->log_options(settings, _codec, _context); + } return true; } diff --git a/source/ui/handler.cpp b/source/ui/handler.cpp index c887858..86d7329 100644 --- a/source/ui/handler.cpp +++ b/source/ui/handler.cpp @@ -20,34 +20,27 @@ // SOFTWARE. #include "handler.hpp" +#include "encoder.hpp" -void obsffmpeg::ui::handler::get_name(const AVCodec*, std::string&) {} - -void obsffmpeg::ui::handler::override_info(obs_encoder_info*, obs_encoder_info*) {} - -void obsffmpeg::ui::handler::override_colorformat(AVPixelFormat&, obs_data_t*, const AVCodec*, AVCodecContext*) {} - -void obsffmpeg::ui::handler::override_lag_in_frames(size_t&, obs_data_t*, const AVCodec*, AVCodecContext*) {} +void obsffmpeg::ui::handler::adjust_encoder_info(obsffmpeg::encoder_factory*, obsffmpeg::encoder_info*, + obsffmpeg::encoder_info*) +{} void obsffmpeg::ui::handler::get_defaults(obs_data_t*, const AVCodec*, AVCodecContext*, bool) {} -void obsffmpeg::ui::handler::get_properties(obs_properties_t*, const AVCodec*, AVCodecContext*, bool) {} - -obsffmpeg::hwapi::device obsffmpeg::ui::handler::find_hw_device(std::shared_ptr, const AVCodec*, - AVCodecContext*) +bool obsffmpeg::ui::handler::has_keyframe_support(obsffmpeg::encoder* instance) { - return obsffmpeg::hwapi::device(); + return (instance->get_avcodec()->capabilities & AV_CODEC_CAP_INTRA_ONLY) == 0; } +void obsffmpeg::ui::handler::get_properties(obs_properties_t*, const AVCodec*, AVCodecContext*, bool) {} + void obsffmpeg::ui::handler::update(obs_data_t*, const AVCodec*, AVCodecContext*) {} +void obsffmpeg::ui::handler::override_update(obsffmpeg::encoder*, obs_data_t*) {} + void obsffmpeg::ui::handler::log_options(obs_data_t*, const AVCodec*, AVCodecContext*) {} -void obsffmpeg::ui::handler::import_from_ffmpeg(const std::string, obs_data_t*, const AVCodec*, AVCodecContext*) {} - -std::string obsffmpeg::ui::handler::export_for_ffmpeg(obs_data_t*, const AVCodec*, AVCodecContext*) -{ - return std::string(); -} +void obsffmpeg::ui::handler::override_colorformat(AVPixelFormat&, obs_data_t*, const AVCodec*, AVCodecContext*) {} void obsffmpeg::ui::handler::process_avpacket(AVPacket&, const AVCodec*, AVCodecContext*) {} diff --git a/source/ui/handler.hpp b/source/ui/handler.hpp index 08acf13..f350a45 100644 --- a/source/ui/handler.hpp +++ b/source/ui/handler.hpp @@ -22,7 +22,6 @@ #pragma once #include -#include "encoder.hpp" #include "hwapi/base.hpp" extern "C" { @@ -38,41 +37,36 @@ extern "C" { } namespace obsffmpeg { + struct encoder_info; + class encoder_factory; + class encoder; + namespace ui { class handler { public /*factory*/: virtual void adjust_encoder_info(obsffmpeg::encoder_factory* factory, obsffmpeg::encoder_info* main, - obsffmpeg::encoder_info* fallback) = 0; - - public /*instance*/: - - virtual void get_name(const AVCodec* codec, std::string& name); - - virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings, - const AVCodec* codec, AVCodecContext* context); - - virtual void override_lag_in_frames(size_t& lag, obs_data_t* settings, const AVCodec* codec, - AVCodecContext* context); + obsffmpeg::encoder_info* fallback); virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, bool hw_encode); + public /*settings*/: + virtual bool has_keyframe_support(obsffmpeg::encoder* instance); + virtual void get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context, bool hw_encode); - virtual obsffmpeg::hwapi::device find_hw_device(std::shared_ptr api, - const AVCodec* codec, AVCodecContext* context); - virtual void update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context); + virtual void override_update(obsffmpeg::encoder* instance, obs_data_t* settings); + virtual void log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context); - virtual void import_from_ffmpeg(const std::string ffmpeg, obs_data_t* settings, - const AVCodec* codec, AVCodecContext* context); + public /*instance*/: - virtual std::string export_for_ffmpeg(obs_data_t* settings, const AVCodec* codec, - AVCodecContext* context); + virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings, + const AVCodec* codec, AVCodecContext* context); virtual void process_avpacket(AVPacket& packet, const AVCodec* codec, AVCodecContext* context); }; diff --git a/source/ui/nvenc_h264_handler.cpp b/source/ui/nvenc_h264_handler.cpp index a28d223..720309c 100644 --- a/source/ui/nvenc_h264_handler.cpp +++ b/source/ui/nvenc_h264_handler.cpp @@ -21,6 +21,7 @@ #include "nvenc_h264_handler.hpp" #include "codecs/h264.hpp" +#include "encoder.hpp" #include "nvenc_shared.hpp" #include "plugin.hpp" #include "strings.hpp" @@ -80,15 +81,11 @@ INITIALIZER(nvenc_h264_handler_init) }); }; -void obsffmpeg::ui::nvenc_h264_handler::get_name(const AVCodec*, std::string& name) +void obsffmpeg::ui::nvenc_h264_handler::adjust_encoder_info(obsffmpeg::encoder_factory*, obsffmpeg::encoder_info* main, + obsffmpeg::encoder_info* fallback) { - name = "H.264/AVC Encoder (NVidia NVENC)"; -} - -void obsffmpeg::ui::nvenc_h264_handler::override_lag_in_frames(size_t& lag, obs_data_t* settings, const AVCodec* codec, - AVCodecContext* context) -{ - nvenc::override_lag_in_frames(lag, settings, codec, context); + main->readable_name = "H.264/AVC Encoder (NVidia NVENC) (Hardware)"; + fallback->readable_name = "H.264/AVC Encoder (NVidia NVENC) (Software)"; } void obsffmpeg::ui::nvenc_h264_handler::get_defaults(obs_data_t* settings, const AVCodec* codec, @@ -100,6 +97,11 @@ void obsffmpeg::ui::nvenc_h264_handler::get_defaults(obs_data_t* settings, const obs_data_set_default_int(settings, P_H264_LEVEL, static_cast(codecs::h264::level::UNKNOWN)); } +bool obsffmpeg::ui::nvenc_h264_handler::has_keyframe_support(obsffmpeg::encoder*) +{ + return true; +} + void obsffmpeg::ui::nvenc_h264_handler::get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context, bool) { @@ -132,6 +134,11 @@ void obsffmpeg::ui::nvenc_h264_handler::update(obs_data_t* settings, const AVCod } } +void obsffmpeg::ui::nvenc_h264_handler::override_update(obsffmpeg::encoder* instance, obs_data_t* settings) +{ + nvenc::override_update(instance, settings); +} + void obsffmpeg::ui::nvenc_h264_handler::log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context) { nvenc::log_options(settings, codec, context); diff --git a/source/ui/nvenc_h264_handler.hpp b/source/ui/nvenc_h264_handler.hpp index 1d9e5ff..a71eaad 100644 --- a/source/ui/nvenc_h264_handler.hpp +++ b/source/ui/nvenc_h264_handler.hpp @@ -33,23 +33,28 @@ extern "C" { namespace obsffmpeg { namespace ui { class nvenc_h264_handler : public handler { - public: - virtual void get_name(const AVCodec* codec, std::string& name) override; - - virtual void override_lag_in_frames(size_t& lag, obs_data_t* settings, const AVCodec* codec, - AVCodecContext* context) override; + public /*factory*/: + virtual void adjust_encoder_info(obsffmpeg::encoder_factory* factory, + obsffmpeg::encoder_info* main, + obsffmpeg::encoder_info* fallback); virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, - bool hw_encode) override; + bool hw_encode); + + public /*settings*/: + virtual bool has_keyframe_support(obsffmpeg::encoder* instance); virtual void get_properties(obs_properties_t* props, const AVCodec* codec, - AVCodecContext* context, bool hw_encode) override; + AVCodecContext* context, bool hw_encode); - virtual void update(obs_data_t* settings, const AVCodec* codec, - AVCodecContext* context) override; + virtual void update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context); - virtual void log_options(obs_data_t* settings, const AVCodec* codec, - AVCodecContext* context) override; + virtual void override_update(obsffmpeg::encoder* 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); private: void get_encoder_properties(obs_properties_t* props, const AVCodec* codec); diff --git a/source/ui/nvenc_hevc_handler.cpp b/source/ui/nvenc_hevc_handler.cpp index 8724ba0..8d8e5c3 100644 --- a/source/ui/nvenc_hevc_handler.cpp +++ b/source/ui/nvenc_hevc_handler.cpp @@ -21,6 +21,7 @@ #include "nvenc_hevc_handler.hpp" #include "codecs/hevc.hpp" +#include "encoder.hpp" #include "nvenc_shared.hpp" #include "plugin.hpp" #include "strings.hpp" @@ -82,15 +83,11 @@ INITIALIZER(nvenc_hevc_handler_init) }); }; -void obsffmpeg::ui::nvenc_hevc_handler::get_name(const AVCodec*, std::string& name) +void obsffmpeg::ui::nvenc_hevc_handler::adjust_encoder_info(obsffmpeg::encoder_factory*, obsffmpeg::encoder_info* main, + obsffmpeg::encoder_info* fallback) { - name = "H.265/HEVC Encoder (NVidia NVENC)"; -} - -void obsffmpeg::ui::nvenc_hevc_handler::override_lag_in_frames(size_t& lag, obs_data_t* settings, const AVCodec* codec, - AVCodecContext* context) -{ - nvenc::override_lag_in_frames(lag, settings, codec, context); + main->readable_name = "H.265/HEVC Encoder (Nvidia NVENC) (Hardware)"; + fallback->readable_name = "H.265/HEVC Encoder (Nvidia NVENC) (Software)"; } void obsffmpeg::ui::nvenc_hevc_handler::get_defaults(obs_data_t* settings, const AVCodec* codec, @@ -103,6 +100,11 @@ void obsffmpeg::ui::nvenc_hevc_handler::get_defaults(obs_data_t* settings, const obs_data_set_default_int(settings, P_HEVC_LEVEL, static_cast(codecs::hevc::level::UNKNOWN)); } +bool obsffmpeg::ui::nvenc_hevc_handler::has_keyframe_support(obsffmpeg::encoder*) +{ + return true; +} + void obsffmpeg::ui::nvenc_hevc_handler::get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context, bool) { @@ -139,6 +141,11 @@ void obsffmpeg::ui::nvenc_hevc_handler::update(obs_data_t* settings, const AVCod } } +void obsffmpeg::ui::nvenc_hevc_handler::override_update(obsffmpeg::encoder* instance, obs_data_t* settings) +{ + nvenc::override_update(instance, settings); +} + void obsffmpeg::ui::nvenc_hevc_handler::log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context) { nvenc::log_options(settings, codec, context); diff --git a/source/ui/nvenc_hevc_handler.hpp b/source/ui/nvenc_hevc_handler.hpp index b251a80..891de4c 100644 --- a/source/ui/nvenc_hevc_handler.hpp +++ b/source/ui/nvenc_hevc_handler.hpp @@ -33,23 +33,28 @@ extern "C" { namespace obsffmpeg { namespace ui { class nvenc_hevc_handler : public handler { - public: - virtual void get_name(const AVCodec* codec, std::string& name) override; - - virtual void override_lag_in_frames(size_t& lag, obs_data_t* settings, const AVCodec* codec, - AVCodecContext* context) override; + public /*factory*/: + virtual void adjust_encoder_info(obsffmpeg::encoder_factory* factory, + obsffmpeg::encoder_info* main, + obsffmpeg::encoder_info* fallback); virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, - bool hw_encode) override; + bool hw_encode); + + public /*settings*/: + virtual bool has_keyframe_support(obsffmpeg::encoder* instance); virtual void get_properties(obs_properties_t* props, const AVCodec* codec, - AVCodecContext* context, bool hw_encode) override; + AVCodecContext* context, bool hw_encode); - virtual void update(obs_data_t* settings, const AVCodec* codec, - AVCodecContext* context) override; + virtual void update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context); - virtual void log_options(obs_data_t* settings, const AVCodec* codec, - AVCodecContext* context) override; + virtual void override_update(obsffmpeg::encoder* 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); private: void get_encoder_properties(obs_properties_t* props, const AVCodec* codec); diff --git a/source/ui/nvenc_shared.cpp b/source/ui/nvenc_shared.cpp index db477ba..8e2e1f8 100644 --- a/source/ui/nvenc_shared.cpp +++ b/source/ui/nvenc_shared.cpp @@ -22,6 +22,7 @@ #include "nvenc_shared.hpp" #include #include "codecs/hevc.hpp" +#include "encoder.hpp" #include "plugin.hpp" #include "strings.hpp" #include "utility.hpp" @@ -132,17 +133,34 @@ std::map obsffmpeg::nvenc::b_ref_mode_to_opt{ {b_ref_mode::MIDDLE, "middle"}, }; -void obsffmpeg::nvenc::override_lag_in_frames(size_t& lag, obs_data_t*, const AVCodec*, AVCodecContext* context) +void obsffmpeg::nvenc::override_update(obsffmpeg::encoder* instance, obs_data_t*) { - // With NVENC, the number of frames lagged before we get our first - // packet is determined by the number of b-frames. Threads, lookahead - // frames and various other settings are ignored. - // The minimum number of lagged frames is 1. + AVCodecContext* context = const_cast(instance->get_avcodeccontext()); - int64_t rcla = 0; - av_opt_get_int(context, "rc-lookahead", AV_OPT_SEARCH_CHILDREN, &rcla); + int64_t rclookahead = 0; + int64_t surfaces = 0; + int64_t async_depth = 0; - lag = static_cast(std::max(1ll + static_cast(context->max_b_frames), rcla)); + av_opt_get_int(context, "rc-lookahead", AV_OPT_SEARCH_CHILDREN, &rclookahead); + av_opt_get_int(context, "surfaces", AV_OPT_SEARCH_CHILDREN, &surfaces); + av_opt_get_int(context, "async_depth", AV_OPT_SEARCH_CHILDREN, &async_depth); + + // Calculate and set the number of surfaces to allocate (if not user overridden). + if (surfaces == 0) { + surfaces = std::max(4ll, (context->max_b_frames + 1ll) * 4ll); + if (rclookahead > 0) { + surfaces = std::max(1ll, std::max(surfaces, rclookahead + (context->max_b_frames + 5ll))); + } else if (context->max_b_frames > 0) { + surfaces = std::max(4ll, (context->max_b_frames + 1ll) * 4ll); + } else { + surfaces = 4; + } + + av_opt_set_int(context, "surfaces", surfaces, AV_OPT_SEARCH_CHILDREN); + } + + // Set delay + context->delay = static_cast(std::min(std::max(async_depth, 3ll), surfaces - 1)); } void obsffmpeg::nvenc::get_defaults(obs_data_t* settings, const AVCodec*, AVCodecContext*) diff --git a/source/ui/nvenc_shared.hpp b/source/ui/nvenc_shared.hpp index 577ed59..b800b5f 100644 --- a/source/ui/nvenc_shared.hpp +++ b/source/ui/nvenc_shared.hpp @@ -32,6 +32,8 @@ extern "C" { } namespace obsffmpeg { + class encoder; + namespace nvenc { enum class preset : int64_t { DEFAULT, @@ -75,8 +77,7 @@ namespace obsffmpeg { extern std::map b_ref_mode_to_opt; - void override_lag_in_frames(size_t& lag, obs_data_t* settings, const AVCodec* codec, - AVCodecContext* context); + void override_update(obsffmpeg::encoder* instance, obs_data_t* settings); void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);