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
|
||||
FFmpegEncoder="FFmpeg Options"
|
||||
FFmpegEncoder.Suffix=" (via FFmpeg)"
|
||||
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.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/swscale.hpp"
|
||||
#include "handlers/handler.hpp"
|
||||
#include "obs/obs-encoder-factory.hpp"
|
||||
|
||||
extern "C" {
|
||||
#ifdef _MSC_VER
|
||||
|
@ -49,54 +50,21 @@ extern "C" {
|
|||
namespace streamfx::encoder::ffmpeg {
|
||||
class ffmpeg_factory;
|
||||
|
||||
struct ffmpeg_info {
|
||||
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;
|
||||
class ffmpeg_instance : public obs::encoder_instance {
|
||||
ffmpeg_factory* _factory;
|
||||
|
||||
const AVCodec* _codec;
|
||||
AVCodecContext* _context;
|
||||
|
||||
std::shared_ptr<handler::handler> _handler;
|
||||
|
||||
::ffmpeg::swscale _scaler;
|
||||
AVPacket _packet;
|
||||
|
||||
std::shared_ptr<::ffmpeg::hwapi::base> _hwapi;
|
||||
std::shared_ptr<::ffmpeg::hwapi::instance> _hwinst;
|
||||
|
||||
::ffmpeg::swscale _swscale;
|
||||
AVPacket _current_packet;
|
||||
|
||||
std::size_t _lag_in_frames;
|
||||
std::size_t _count_send_frames;
|
||||
std::size_t _sent_frames;
|
||||
|
||||
// Extra Data
|
||||
bool _have_first_frame;
|
||||
|
@ -108,6 +76,31 @@ namespace streamfx::encoder::ffmpeg {
|
|||
std::queue<std::shared_ptr<AVFrame>> _used_frames;
|
||||
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_hw(obs_data_t* settings);
|
||||
|
||||
|
@ -117,35 +110,6 @@ namespace streamfx::encoder::ffmpeg {
|
|||
void push_used_frame(std::shared_ptr<AVFrame> 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 send_frame(std::shared_ptr<AVFrame> frame);
|
||||
|
@ -162,6 +126,29 @@ namespace streamfx::encoder::ffmpeg {
|
|||
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 {
|
||||
std::map<const AVCodec*, std::shared_ptr<ffmpeg_factory>> _factories;
|
||||
std::map<std::string, std::shared_ptr<handler::handler>> _handlers;
|
||||
|
@ -171,14 +158,14 @@ namespace streamfx::encoder::ffmpeg {
|
|||
ffmpeg_manager();
|
||||
~ffmpeg_manager();
|
||||
|
||||
void register_encoders();
|
||||
|
||||
void register_handler(std::string codec, std::shared_ptr<handler::handler> handler);
|
||||
|
||||
std::shared_ptr<handler::handler> get_handler(std::string codec);
|
||||
|
||||
bool has_handler(std::string codec);
|
||||
|
||||
void register_encoders();
|
||||
|
||||
public: // Singleton
|
||||
static void initialize();
|
||||
|
||||
|
|
|
@ -24,10 +24,6 @@
|
|||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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(){};
|
||||
|
||||
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);
|
||||
bool hw_encode){};
|
||||
|
||||
public /*support tests*/:
|
||||
virtual bool has_keyframe_support(ffmpeg_factory* instance);
|
||||
|
@ -57,20 +58,20 @@ namespace streamfx::encoder::ffmpeg {
|
|||
|
||||
public /*settings*/:
|
||||
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*/:
|
||||
|
||||
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 streamfx::encoder::ffmpeg
|
||||
|
|
|
@ -60,11 +60,9 @@ std::map<level, std::string> levels{
|
|||
{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";
|
||||
fallback->readable_name = "H.264/AVC NVidia NVENC (Software Fallback)";
|
||||
fallback->oei.caps |= OBS_ENCODER_CAP_DEPRECATED;
|
||||
name = "NVIDIA NVENC H.264/AVC Encoder";
|
||||
}
|
||||
|
||||
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(){};
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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"},
|
||||
};
|
||||
|
||||
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";
|
||||
fallback->readable_name = "H.265/HEVC Nvidia NVENC (Software Fallback)";
|
||||
fallback->oei.caps |= OBS_ENCODER_CAP_DEPRECATED;
|
||||
name = "NVIDIA NVENC H.265/HEVC Encoder";
|
||||
}
|
||||
|
||||
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(){};
|
||||
|
||||
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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue