// AUTOGENERATED COPYRIGHT HEADER START // Copyright (C) 2020-2023 Michael Fabian 'Xaymar' Dirks // Copyright (C) 2022 lainon // AUTOGENERATED COPYRIGHT HEADER END #pragma once #include "common.hpp" #include "ffmpeg/avframe-queue.hpp" #include "ffmpeg/hwapi/base.hpp" #include "ffmpeg/swscale.hpp" #include "handlers/handler.hpp" #include "obs/obs-encoder-factory.hpp" #include "warning-disable.hpp" #include #include #include #include #include #include #include #include "warning-enable.hpp" extern "C" { #include "warning-disable.hpp" #include #include #include "warning-enable.hpp" } namespace streamfx::encoder::ffmpeg { class ffmpeg_factory; class ffmpeg_instance : public obs::encoder_instance { ffmpeg_factory* _factory; const AVCodec* _codec; AVCodecContext* _context; std::shared_ptr _handler; ::streamfx::ffmpeg::swscale _scaler; std::shared_ptr _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 _extra_data; std::vector _sei_data; // Frame Stack and Queue std::stack> _free_frames; std::queue> _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 frame); std::shared_ptr pop_free_frame(); void push_used_frame(std::shared_ptr frame); std::shared_ptr pop_used_frame(); int receive_packet(bool* received_packet, struct encoder_packet* packet); int send_frame(std::shared_ptr frame); bool encode_avframe(std::shared_ptr 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 { std::string _id; std::string _codec; std::string _name; const AVCodec* _avcodec; std::shared_ptr _handler; public: ffmpeg_factory(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> _factories; std::map> _handlers; std::shared_ptr _debug_handler; public: ffmpeg_manager(); ~ffmpeg_manager(); void register_encoders(); void register_handler(std::string codec, std::shared_ptr handler); std::shared_ptr get_handler(std::string codec); bool has_handler(std::string_view codec); public: // Singleton static void initialize(); static void finalize(); static std::shared_ptr get(); }; } // namespace streamfx::encoder::ffmpeg