mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-11-30 15:23:01 +00:00
c4461e70b9
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.
158 lines
4.4 KiB
C++
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
|