mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-12-29 11:01:23 +00:00
encoders/ffmpeg: Rebase onto obs::encoder_factory
This commit is contained in:
parent
d3c2f288b4
commit
ce93f96a69
9 changed files with 611 additions and 918 deletions
|
@ -378,6 +378,7 @@ Codec.ProRes.Profile.AP4X="4444 Extreme Quality/XQ (AP4X)"
|
||||||
|
|
||||||
# Encoder: FFmpeg
|
# Encoder: FFmpeg
|
||||||
FFmpegEncoder="FFmpeg Options"
|
FFmpegEncoder="FFmpeg Options"
|
||||||
|
FFmpegEncoder.Suffix=" (via FFmpeg)"
|
||||||
FFmpegEncoder.CustomSettings="Custom Settings"
|
FFmpegEncoder.CustomSettings="Custom Settings"
|
||||||
FFmpegEncoder.CustomSettings.Description="Override any options shown (or not shown) above with your own.\nThe format is similar to that of the FFmpeg command line:\n -key=value -key2=value2 -key3='quoted value'"
|
FFmpegEncoder.CustomSettings.Description="Override any options shown (or not shown) above with your own.\nThe format is similar to that of the FFmpeg command line:\n -key=value -key2=value2 -key3='quoted value'"
|
||||||
FFmpegEncoder.Threads="Number of Threads"
|
FFmpegEncoder.Threads="Number of Threads"
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -32,6 +32,7 @@
|
||||||
#include "ffmpeg/hwapi/base.hpp"
|
#include "ffmpeg/hwapi/base.hpp"
|
||||||
#include "ffmpeg/swscale.hpp"
|
#include "ffmpeg/swscale.hpp"
|
||||||
#include "handlers/handler.hpp"
|
#include "handlers/handler.hpp"
|
||||||
|
#include "obs/obs-encoder-factory.hpp"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
@ -49,54 +50,21 @@ extern "C" {
|
||||||
namespace streamfx::encoder::ffmpeg {
|
namespace streamfx::encoder::ffmpeg {
|
||||||
class ffmpeg_factory;
|
class ffmpeg_factory;
|
||||||
|
|
||||||
struct ffmpeg_info {
|
class ffmpeg_instance : public obs::encoder_instance {
|
||||||
std::string uid;
|
|
||||||
std::string codec;
|
|
||||||
std::string readable_name;
|
|
||||||
obs_encoder_info oei = {0};
|
|
||||||
};
|
|
||||||
|
|
||||||
class ffmpeg_factory {
|
|
||||||
ffmpeg_info info;
|
|
||||||
ffmpeg_info info_fallback;
|
|
||||||
const AVCodec* avcodec_ptr;
|
|
||||||
|
|
||||||
std::shared_ptr<handler::handler> _handler;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ffmpeg_factory(const AVCodec* codec);
|
|
||||||
virtual ~ffmpeg_factory();
|
|
||||||
|
|
||||||
void register_encoder();
|
|
||||||
|
|
||||||
void get_defaults(obs_data_t* settings, bool hw_encoder = false);
|
|
||||||
|
|
||||||
void get_properties(obs_properties_t* props, bool hw_encoder = false);
|
|
||||||
|
|
||||||
const AVCodec* get_avcodec();
|
|
||||||
|
|
||||||
const ffmpeg_info& get_info();
|
|
||||||
|
|
||||||
const ffmpeg_info& get_fallback();
|
|
||||||
};
|
|
||||||
|
|
||||||
class ffmpeg_instance {
|
|
||||||
obs_encoder_t* _self;
|
|
||||||
ffmpeg_factory* _factory;
|
ffmpeg_factory* _factory;
|
||||||
|
|
||||||
const AVCodec* _codec;
|
const AVCodec* _codec;
|
||||||
AVCodecContext* _context;
|
AVCodecContext* _context;
|
||||||
|
|
||||||
std::shared_ptr<handler::handler> _handler;
|
std::shared_ptr<handler::handler> _handler;
|
||||||
|
|
||||||
|
::ffmpeg::swscale _scaler;
|
||||||
|
AVPacket _packet;
|
||||||
|
|
||||||
std::shared_ptr<::ffmpeg::hwapi::base> _hwapi;
|
std::shared_ptr<::ffmpeg::hwapi::base> _hwapi;
|
||||||
std::shared_ptr<::ffmpeg::hwapi::instance> _hwinst;
|
std::shared_ptr<::ffmpeg::hwapi::instance> _hwinst;
|
||||||
|
|
||||||
::ffmpeg::swscale _swscale;
|
|
||||||
AVPacket _current_packet;
|
|
||||||
|
|
||||||
std::size_t _lag_in_frames;
|
std::size_t _lag_in_frames;
|
||||||
std::size_t _count_send_frames;
|
std::size_t _sent_frames;
|
||||||
|
|
||||||
// Extra Data
|
// Extra Data
|
||||||
bool _have_first_frame;
|
bool _have_first_frame;
|
||||||
|
@ -108,6 +76,31 @@ namespace streamfx::encoder::ffmpeg {
|
||||||
std::queue<std::shared_ptr<AVFrame>> _used_frames;
|
std::queue<std::shared_ptr<AVFrame>> _used_frames;
|
||||||
std::chrono::high_resolution_clock::time_point _free_frames_last_used;
|
std::chrono::high_resolution_clock::time_point _free_frames_last_used;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ffmpeg_instance(obs_data_t* settings, obs_encoder_t* self);
|
||||||
|
virtual ~ffmpeg_instance();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void get_properties(obs_properties_t* props);
|
||||||
|
|
||||||
|
void migrate(obs_data_t* settings, std::uint64_t version) override;
|
||||||
|
|
||||||
|
bool update(obs_data_t* settings) override;
|
||||||
|
|
||||||
|
bool encode_audio(struct encoder_frame* frame, struct encoder_packet* packet, bool* received_packet) override;
|
||||||
|
|
||||||
|
bool encode_video(struct encoder_frame* frame, struct encoder_packet* packet, bool* received_packet) override;
|
||||||
|
|
||||||
|
bool encode_video(uint32_t handle, int64_t pts, uint64_t lock_key, uint64_t* next_key,
|
||||||
|
struct encoder_packet* packet, bool* received_packet) override;
|
||||||
|
|
||||||
|
bool get_extra_data(uint8_t** extra_data, size_t* size) override;
|
||||||
|
|
||||||
|
bool get_sei_data(uint8_t** sei_data, size_t* size) override;
|
||||||
|
|
||||||
|
void get_video_info(struct video_scale_info* info) override;
|
||||||
|
|
||||||
|
public:
|
||||||
void initialize_sw(obs_data_t* settings);
|
void initialize_sw(obs_data_t* settings);
|
||||||
void initialize_hw(obs_data_t* settings);
|
void initialize_hw(obs_data_t* settings);
|
||||||
|
|
||||||
|
@ -117,35 +110,6 @@ namespace streamfx::encoder::ffmpeg {
|
||||||
void push_used_frame(std::shared_ptr<AVFrame> frame);
|
void push_used_frame(std::shared_ptr<AVFrame> frame);
|
||||||
std::shared_ptr<AVFrame> pop_used_frame();
|
std::shared_ptr<AVFrame> pop_used_frame();
|
||||||
|
|
||||||
public:
|
|
||||||
ffmpeg_instance(obs_data_t* settings, obs_encoder_t* encoder, bool is_texture_encode = false);
|
|
||||||
virtual ~ffmpeg_instance();
|
|
||||||
|
|
||||||
public: // OBS API
|
|
||||||
// Shared
|
|
||||||
void get_properties(obs_properties_t* props, bool hw_encode = false);
|
|
||||||
|
|
||||||
bool update(obs_data_t* settings);
|
|
||||||
|
|
||||||
// Audio only
|
|
||||||
void get_audio_info(struct audio_convert_info* info);
|
|
||||||
|
|
||||||
std::size_t get_frame_size();
|
|
||||||
|
|
||||||
bool audio_encode(struct encoder_frame* frame, struct encoder_packet* packet, bool* received_packet);
|
|
||||||
|
|
||||||
// Video only
|
|
||||||
void get_video_info(struct video_scale_info* info);
|
|
||||||
|
|
||||||
bool get_sei_data(std::uint8_t** sei_data, size_t* size);
|
|
||||||
|
|
||||||
bool get_extra_data(std::uint8_t** extra_data, size_t* size);
|
|
||||||
|
|
||||||
bool video_encode(struct encoder_frame* frame, struct encoder_packet* packet, bool* received_packet);
|
|
||||||
|
|
||||||
bool video_encode_texture(std::uint32_t handle, std::int64_t pts, std::uint64_t lock_key,
|
|
||||||
std::uint64_t* next_key, struct encoder_packet* packet, bool* received_packet);
|
|
||||||
|
|
||||||
int receive_packet(bool* received_packet, struct encoder_packet* packet);
|
int receive_packet(bool* received_packet, struct encoder_packet* packet);
|
||||||
|
|
||||||
int send_frame(std::shared_ptr<AVFrame> frame);
|
int send_frame(std::shared_ptr<AVFrame> frame);
|
||||||
|
@ -162,6 +126,29 @@ namespace streamfx::encoder::ffmpeg {
|
||||||
void parse_ffmpeg_commandline(std::string text);
|
void parse_ffmpeg_commandline(std::string text);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ffmpeg_factory : public obs::encoder_factory<ffmpeg_factory, ffmpeg_instance> {
|
||||||
|
std::string _id;
|
||||||
|
std::string _codec;
|
||||||
|
std::string _name;
|
||||||
|
|
||||||
|
const AVCodec* _avcodec;
|
||||||
|
|
||||||
|
std::shared_ptr<handler::handler> _handler;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ffmpeg_factory(const AVCodec* codec);
|
||||||
|
virtual ~ffmpeg_factory();
|
||||||
|
|
||||||
|
const char* get_name() override;
|
||||||
|
|
||||||
|
void get_defaults2(obs_data_t* data) override;
|
||||||
|
|
||||||
|
obs_properties_t* get_properties2(instance_t* data) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const AVCodec* get_avcodec();
|
||||||
|
};
|
||||||
|
|
||||||
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::map<std::string, std::shared_ptr<handler::handler>> _handlers;
|
||||||
|
@ -171,14 +158,14 @@ namespace streamfx::encoder::ffmpeg {
|
||||||
ffmpeg_manager();
|
ffmpeg_manager();
|
||||||
~ffmpeg_manager();
|
~ffmpeg_manager();
|
||||||
|
|
||||||
|
void register_encoders();
|
||||||
|
|
||||||
void register_handler(std::string codec, std::shared_ptr<handler::handler> handler);
|
void register_handler(std::string codec, std::shared_ptr<handler::handler> handler);
|
||||||
|
|
||||||
std::shared_ptr<handler::handler> get_handler(std::string codec);
|
std::shared_ptr<handler::handler> get_handler(std::string codec);
|
||||||
|
|
||||||
bool has_handler(std::string codec);
|
bool has_handler(std::string codec);
|
||||||
|
|
||||||
void register_encoders();
|
|
||||||
|
|
||||||
public: // Singleton
|
public: // Singleton
|
||||||
static void initialize();
|
static void initialize();
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,6 @@
|
||||||
|
|
||||||
using namespace streamfx::encoder::ffmpeg;
|
using namespace streamfx::encoder::ffmpeg;
|
||||||
|
|
||||||
void handler::handler::adjust_encoder_info(ffmpeg_factory*, ffmpeg_info*, ffmpeg_info*) {}
|
|
||||||
|
|
||||||
void handler::handler::get_defaults(obs_data_t*, const AVCodec*, AVCodecContext*, bool) {}
|
|
||||||
|
|
||||||
bool handler::handler::has_keyframe_support(ffmpeg_factory* instance)
|
bool handler::handler::has_keyframe_support(ffmpeg_factory* instance)
|
||||||
{
|
{
|
||||||
return (instance->get_avcodec()->capabilities & AV_CODEC_CAP_INTRA_ONLY) == 0;
|
return (instance->get_avcodec()->capabilities & AV_CODEC_CAP_INTRA_ONLY) == 0;
|
||||||
|
@ -47,15 +43,3 @@ bool handler::handler::has_pixel_format_support(ffmpeg_factory* instance)
|
||||||
{
|
{
|
||||||
return (instance->get_avcodec()->pix_fmts != nullptr);
|
return (instance->get_avcodec()->pix_fmts != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handler::handler::get_properties(obs_properties_t*, const AVCodec*, AVCodecContext*, bool) {}
|
|
||||||
|
|
||||||
void handler::handler::update(obs_data_t*, const AVCodec*, AVCodecContext*) {}
|
|
||||||
|
|
||||||
void handler::handler::override_update(ffmpeg_instance*, obs_data_t*) {}
|
|
||||||
|
|
||||||
void handler::handler::log_options(obs_data_t*, const AVCodec*, AVCodecContext*) {}
|
|
||||||
|
|
||||||
void handler::handler::override_colorformat(AVPixelFormat&, obs_data_t*, const AVCodec*, AVCodecContext*) {}
|
|
||||||
|
|
||||||
void handler::handler::process_avpacket(AVPacket&, const AVCodec*, AVCodecContext*) {}
|
|
||||||
|
|
|
@ -41,10 +41,11 @@ namespace streamfx::encoder::ffmpeg {
|
||||||
virtual ~handler(){};
|
virtual ~handler(){};
|
||||||
|
|
||||||
public /*factory*/:
|
public /*factory*/:
|
||||||
virtual void adjust_encoder_info(ffmpeg_factory* factory, ffmpeg_info* main, ffmpeg_info* fallback);
|
virtual void adjust_info(ffmpeg_factory* factory, const AVCodec* codec, std::string& id, std::string& name,
|
||||||
|
std::string& codec_id){};
|
||||||
|
|
||||||
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context,
|
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context,
|
||||||
bool hw_encode);
|
bool hw_encode){};
|
||||||
|
|
||||||
public /*support tests*/:
|
public /*support tests*/:
|
||||||
virtual bool has_keyframe_support(ffmpeg_factory* instance);
|
virtual bool has_keyframe_support(ffmpeg_factory* instance);
|
||||||
|
@ -57,20 +58,20 @@ namespace streamfx::encoder::ffmpeg {
|
||||||
|
|
||||||
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){};
|
||||||
|
|
||||||
virtual void update(obs_data_t* settings, 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 override_update(ffmpeg_instance* instance, obs_data_t* settings){};
|
||||||
|
|
||||||
virtual void log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
virtual void log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context){};
|
||||||
|
|
||||||
public /*instance*/:
|
public /*instance*/:
|
||||||
|
|
||||||
virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings, const AVCodec* codec,
|
virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings, const AVCodec* codec,
|
||||||
AVCodecContext* context);
|
AVCodecContext* context){};
|
||||||
|
|
||||||
virtual void process_avpacket(AVPacket& packet, const AVCodec* codec, AVCodecContext* context);
|
virtual void process_avpacket(AVPacket& packet, const AVCodec* codec, AVCodecContext* context){};
|
||||||
};
|
};
|
||||||
} // namespace handler
|
} // namespace handler
|
||||||
} // namespace streamfx::encoder::ffmpeg
|
} // namespace streamfx::encoder::ffmpeg
|
||||||
|
|
|
@ -60,11 +60,9 @@ std::map<level, std::string> levels{
|
||||||
{level::L5_1, "5.1"}, {level::L5_2, "5.2"},
|
{level::L5_1, "5.1"}, {level::L5_2, "5.2"},
|
||||||
};
|
};
|
||||||
|
|
||||||
void nvenc_h264_handler::adjust_encoder_info(ffmpeg_factory*, ffmpeg_info* main, ffmpeg_info* fallback)
|
void nvenc_h264_handler::adjust_info(ffmpeg_factory*, const AVCodec*, std::string&, std::string& name, std::string&)
|
||||||
{
|
{
|
||||||
main->readable_name = "H.264/AVC NVidia NVENC";
|
name = "NVIDIA NVENC H.264/AVC Encoder";
|
||||||
fallback->readable_name = "H.264/AVC NVidia NVENC (Software Fallback)";
|
|
||||||
fallback->oei.caps |= OBS_ENCODER_CAP_DEPRECATED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvenc_h264_handler::get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, bool)
|
void nvenc_h264_handler::get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, bool)
|
||||||
|
|
|
@ -35,7 +35,8 @@ namespace streamfx::encoder::ffmpeg::handler {
|
||||||
virtual ~nvenc_h264_handler(){};
|
virtual ~nvenc_h264_handler(){};
|
||||||
|
|
||||||
public /*factory*/:
|
public /*factory*/:
|
||||||
virtual void adjust_encoder_info(ffmpeg_factory* factory, ffmpeg_info* main, ffmpeg_info* fallback);
|
virtual void adjust_info(ffmpeg_factory* factory, const AVCodec* codec, std::string& id, std::string& name,
|
||||||
|
std::string& codec_id);
|
||||||
|
|
||||||
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, bool hw_encode);
|
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, bool hw_encode);
|
||||||
|
|
||||||
|
|
|
@ -60,11 +60,9 @@ std::map<level, std::string> levels{
|
||||||
{level::L6_0, "6.0"}, {level::L6_1, "6.1"}, {level::L6_2, "6.2"},
|
{level::L6_0, "6.0"}, {level::L6_1, "6.1"}, {level::L6_2, "6.2"},
|
||||||
};
|
};
|
||||||
|
|
||||||
void nvenc_hevc_handler::adjust_encoder_info(ffmpeg_factory*, ffmpeg_info* main, ffmpeg_info* fallback)
|
void nvenc_hevc_handler::adjust_info(ffmpeg_factory*, const AVCodec*, std::string&, std::string& name, std::string&)
|
||||||
{
|
{
|
||||||
main->readable_name = "H.265/HEVC Nvidia NVENC";
|
name = "NVIDIA NVENC H.265/HEVC Encoder";
|
||||||
fallback->readable_name = "H.265/HEVC Nvidia NVENC (Software Fallback)";
|
|
||||||
fallback->oei.caps |= OBS_ENCODER_CAP_DEPRECATED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvenc_hevc_handler::get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, bool)
|
void nvenc_hevc_handler::get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, bool)
|
||||||
|
|
|
@ -35,7 +35,8 @@ namespace streamfx::encoder::ffmpeg::handler {
|
||||||
virtual ~nvenc_hevc_handler(){};
|
virtual ~nvenc_hevc_handler(){};
|
||||||
|
|
||||||
public /*factory*/:
|
public /*factory*/:
|
||||||
virtual void adjust_encoder_info(ffmpeg_factory* factory, ffmpeg_info* main, ffmpeg_info* fallback);
|
virtual void adjust_info(ffmpeg_factory* factory, const AVCodec* codec, std::string& id, std::string& name,
|
||||||
|
std::string& codec_id);
|
||||||
|
|
||||||
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, bool hw_encode);
|
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, bool hw_encode);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue