obs-StreamFX/source/encoders/encoder-ffmpeg.hpp
Michael Fabian 'Xaymar' Dirks c4461e70b9 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.
2023-05-16 15:19:11 +02:00

158 lines
4.4 KiB
C++

// AUTOGENERATED COPYRIGHT HEADER START
// Copyright (C) 2020-2023 Michael Fabian 'Xaymar' Dirks <info@xaymar.com>
// Copyright (C) 2022 lainon <GermanAizek@yandex.ru>
// AUTOGENERATED COPYRIGHT HEADER END
#pragma once
#include "common.hpp"
#include "encoders/ffmpeg/handler.hpp"
#include "ffmpeg/avframe-queue.hpp"
#include "ffmpeg/hwapi/base.hpp"
#include "ffmpeg/swscale.hpp"
#include "obs/obs-encoder-factory.hpp"
#include "warning-disable.hpp"
#include <condition_variable>
#include <map>
#include <mutex>
#include <queue>
#include <stack>
#include <string>
#include <string_view>
#include <thread>
#include <vector>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/frame.h>
}
#include "warning-enable.hpp"
namespace streamfx::encoder::ffmpeg {
class ffmpeg_instance;
class ffmpeg_factory;
class ffmpeg_manager;
class ffmpeg_instance : public obs::encoder_instance {
ffmpeg_factory* _factory;
const AVCodec* _codec;
AVCodecContext* _context;
streamfx::encoder::ffmpeg::handler* _handler;
::streamfx::ffmpeg::swscale _scaler;
std::shared_ptr<AVPacket> _packet;
std::shared_ptr<::streamfx::ffmpeg::hwapi::base> _hwapi;
std::shared_ptr<::streamfx::ffmpeg::hwapi::instance> _hwinst;
std::size_t _lag_in_frames;
std::size_t _sent_frames;
std::size_t _framerate_divisor;
// Extra Data
bool _have_first_frame;
std::vector<uint8_t> _extra_data;
std::vector<uint8_t> _sei_data;
// Frame Stack and Queue
std::stack<std::shared_ptr<AVFrame>> _free_frames;
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, bool is_hw);
virtual ~ffmpeg_instance();
public:
void get_properties(obs_properties_t* props);
void migrate(obs_data_t* settings, 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);
void push_free_frame(std::shared_ptr<AVFrame> frame);
std::shared_ptr<AVFrame> pop_free_frame();
void push_used_frame(std::shared_ptr<AVFrame> frame);
std::shared_ptr<AVFrame> pop_used_frame();
int receive_packet(bool* received_packet, struct encoder_packet* packet);
int send_frame(std::shared_ptr<AVFrame> frame);
bool encode_avframe(std::shared_ptr<AVFrame> frame, struct encoder_packet* packet, bool* received_packet);
public: // Handler API
bool is_hardware_encode();
const AVCodec* get_avcodec();
const AVCodecContext* get_avcodeccontext();
void parse_ffmpeg_commandline(std::string_view text);
};
class ffmpeg_factory : public obs::encoder_factory<ffmpeg_factory, ffmpeg_instance> {
std::string _id;
std::string _codec;
std::string _name;
const AVCodec* _avcodec;
streamfx::encoder::ffmpeg::handler* _handler;
public:
ffmpeg_factory(ffmpeg_manager* manager, const AVCodec* codec);
virtual ~ffmpeg_factory();
const char* get_name() override;
void get_defaults2(obs_data_t* data) override;
void migrate(obs_data_t* data, uint64_t version) override;
obs_properties_t* get_properties2(instance_t* data) override;
#ifdef ENABLE_FRONTEND
static bool on_manual_open(obs_properties_t* props, obs_property_t* property, void* data);
#endif
public:
const AVCodec* get_avcodec();
obs_encoder_info* get_info();
};
class ffmpeg_manager {
std::map<const AVCodec*, std::shared_ptr<ffmpeg_factory>> _factories;
public:
ffmpeg_manager();
~ffmpeg_manager();
streamfx::encoder::ffmpeg::handler* find_handler(std::string_view codec);
streamfx::encoder::ffmpeg::handler* get_handler(std::string_view codec);
bool has_handler(std::string_view codec);
public: // Singleton
static std::shared_ptr<ffmpeg_manager> instance();
};
} // namespace streamfx::encoder::ffmpeg