2023-02-28 01:15:26 +00:00
// 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
2020-06-14 18:16:26 +00:00
# pragma once
# include "common.hpp"
# include "plugin.hpp"
2021-06-08 02:36:30 +00:00
namespace streamfx : : obs {
2021-08-26 22:21:51 +00:00
class encoder_instance {
protected :
obs_encoder_t * _self ;
public :
encoder_instance ( obs_data_t * settings , obs_encoder_t * self , bool is_hw ) : _self ( self ) { }
virtual ~ encoder_instance ( ) { } ;
virtual void migrate ( obs_data_t * settings , uint64_t version ) { }
virtual bool update ( obs_data_t * settings )
{
return false ;
}
virtual bool encode ( struct encoder_frame * frame , struct encoder_packet * packet , bool * received_packet )
{
auto type = obs_encoder_get_type ( _self ) ;
if ( type = = OBS_ENCODER_VIDEO ) {
return encode_video ( frame , packet , received_packet ) ;
} else if ( type = = OBS_ENCODER_AUDIO ) {
return encode_audio ( frame , packet , received_packet ) ;
}
return false ;
}
virtual bool encode_audio ( struct encoder_frame * frame , struct encoder_packet * packet , bool * received_packet )
{
return false ;
} ;
virtual bool encode_video ( struct encoder_frame * frame , struct encoder_packet * packet , bool * received_packet )
{
return false ;
} ;
2023-05-13 12:35:46 +00:00
virtual bool encode_video ( uint32_t handle , int64_t pts , uint64_t lock_key , uint64_t * next_key , struct encoder_packet * packet , bool * received_packet )
2021-08-26 22:21:51 +00:00
{
return false ;
} ;
virtual size_t get_frame_size ( )
{
return 0 ;
}
virtual bool get_extra_data ( uint8_t * * extra_data , size_t * size )
{
return false ;
}
virtual bool get_sei_data ( uint8_t * * sei_data , size_t * size )
{
return false ;
}
virtual void get_audio_info ( struct audio_convert_info * info ) { }
virtual void get_video_info ( struct video_scale_info * info ) { }
2021-12-02 15:57:48 +00:00
virtual obs_encoder_t * get ( )
{
return _self ;
}
2021-08-26 22:21:51 +00:00
} ;
2020-06-14 18:16:26 +00:00
template < class _factory , typename _instance >
class encoder_factory {
public :
typedef _factory factory_t ;
typedef _instance instance_t ;
protected :
obs_encoder_info _info = { } ;
obs_encoder_info _info_fallback = { } ;
std : : string _info_fallback_id ;
std : : map < std : : string , std : : shared_ptr < obs_encoder_info > > _proxies ;
std : : set < std : : string > _proxy_names ;
public :
encoder_factory ( )
{
_info . type_data = this ;
_info . get_name = _get_name ;
2020-07-27 17:44:27 +00:00
_info . create = _create_hw ;
2020-06-14 18:16:26 +00:00
_info . destroy = _destroy ;
_info . get_defaults2 = _get_defaults2 ;
_info . get_properties2 = _get_properties2 ;
_info . update = _update ;
_info . encode = _encode ;
_info . get_extra_data = _get_extra_data ;
_info . get_sei_data = _get_sei_data ;
}
2022-07-21 11:09:10 +00:00
virtual ~ encoder_factory ( ) = default ;
2020-06-14 18:16:26 +00:00
void finish_setup ( )
{
if ( _info . type = = OBS_ENCODER_AUDIO ) {
_info . get_frame_size = _get_frame_size ;
_info . get_audio_info = _get_audio_info ;
} else if ( _info . type = = OBS_ENCODER_VIDEO ) {
_info . get_video_info = _get_video_info ;
}
if ( _info . caps & OBS_ENCODER_CAP_PASS_TEXTURE ) {
_info . encode_texture = _encode_texture ;
memcpy ( & _info_fallback , & _info , sizeof ( obs_encoder_info ) ) ;
2023-05-13 12:35:46 +00:00
_info_fallback_id = std : : string ( _info . id ) + " _sw " ;
_info_fallback . id = _info_fallback_id . c_str ( ) ;
_info_fallback . caps = ( _info_fallback . caps & ~ OBS_ENCODER_CAP_PASS_TEXTURE ) | OBS_ENCODER_CAP_DEPRECATED ;
2020-07-27 17:44:27 +00:00
_info_fallback . create = _create ;
2020-06-14 18:16:26 +00:00
_info_fallback . encode_texture = nullptr ;
2020-07-27 17:44:27 +00:00
obs_register_encoder ( & _info_fallback ) ;
} else {
_info . create = _create ;
2020-06-14 18:16:26 +00:00
}
obs_register_encoder ( & _info ) ;
}
void register_proxy ( std : : string_view name )
{
auto iter = _proxy_names . emplace ( name ) ;
// Create proxy.
std : : shared_ptr < obs_encoder_info > proxy = std : : make_shared < obs_encoder_info > ( ) ;
memcpy ( proxy . get ( ) , & _info , sizeof ( obs_encoder_info ) ) ;
2020-06-22 20:39:35 +00:00
proxy - > id = iter . first - > c_str ( ) ;
proxy - > caps | = OBS_ENCODER_CAP_DEPRECATED ;
2020-06-14 18:16:26 +00:00
obs_register_encoder ( proxy . get ( ) ) ;
_proxies . emplace ( name , proxy ) ;
}
2021-12-02 15:57:48 +00:00
private :
void _migrate ( obs_data_t * settings , encoder_instance * instance )
{
uint64_t version = static_cast < uint64_t > ( obs_data_get_int ( settings , S_VERSION ) ) ;
migrate ( settings , version ) ;
if ( instance ) {
instance - > migrate ( settings , version ) ;
}
obs_data_set_int ( settings , S_VERSION , static_cast < int64_t > ( STREAMFX_VERSION ) ) ;
2022-06-21 17:09:45 +00:00
obs_data_set_string ( settings , S_COMMIT , STREAMFX_VERSION_BUILD ) ;
2021-12-02 15:57:48 +00:00
}
2020-06-14 18:16:26 +00:00
private /* Factory */ :
static const char * _get_name ( void * type_data ) noexcept
2022-08-27 11:17:47 +00:00
{
try {
if ( type_data )
return reinterpret_cast < factory_t * > ( type_data ) - > get_name ( ) ;
return nullptr ;
} catch ( const std : : exception & ex ) {
DLOG_ERROR ( " Unexpected exception in function '%s': %s. " , __FUNCTION_NAME__ , ex . what ( ) ) ;
return nullptr ;
} catch ( . . . ) {
DLOG_ERROR ( " Unexpected exception in function '%s'. " , __FUNCTION_NAME__ ) ;
return nullptr ;
}
2020-06-14 18:16:26 +00:00
}
static void * _create ( obs_data_t * settings , obs_encoder_t * encoder ) noexcept
2022-08-27 11:17:47 +00:00
{
try {
auto * fac = reinterpret_cast < factory_t * > ( obs_encoder_get_type_data ( encoder ) ) ;
return fac - > create ( settings , encoder , false ) ;
} catch ( const std : : exception & ex ) {
DLOG_ERROR ( " Unexpected exception in function '%s': %s. " , __FUNCTION_NAME__ , ex . what ( ) ) ;
return nullptr ;
} catch ( . . . ) {
DLOG_ERROR ( " Unexpected exception in function '%s'. " , __FUNCTION_NAME__ ) ;
return nullptr ;
}
2020-07-27 17:44:27 +00:00
}
static void * _create_hw ( obs_data_t * settings , obs_encoder_t * encoder ) noexcept
2022-08-27 11:17:47 +00:00
{
2020-06-14 18:16:26 +00:00
try {
2022-08-27 11:17:47 +00:00
auto * fac = reinterpret_cast < factory_t * > ( obs_encoder_get_type_data ( encoder ) ) ;
try {
return fac - > create ( settings , encoder , true ) ;
} catch ( . . . ) {
return obs_encoder_create_rerouted ( encoder , fac - > _info_fallback . id ) ;
}
} catch ( const std : : exception & ex ) {
DLOG_ERROR ( " Unexpected exception in function '%s': %s. " , __FUNCTION_NAME__ , ex . what ( ) ) ;
return nullptr ;
2020-07-27 17:44:27 +00:00
} catch ( . . . ) {
2022-08-27 11:17:47 +00:00
DLOG_ERROR ( " Unexpected exception in function '%s'. " , __FUNCTION_NAME__ ) ;
return nullptr ;
2020-06-14 18:16:26 +00:00
}
}
static void _get_defaults2 ( obs_data_t * settings , void * type_data ) noexcept
2022-08-27 11:17:47 +00:00
{
try {
if ( type_data )
reinterpret_cast < factory_t * > ( type_data ) - > get_defaults2 ( settings ) ;
} catch ( const std : : exception & ex ) {
DLOG_ERROR ( " Unexpected exception in function '%s': %s. " , __FUNCTION_NAME__ , ex . what ( ) ) ;
} catch ( . . . ) {
DLOG_ERROR ( " Unexpected exception in function '%s'. " , __FUNCTION_NAME__ ) ;
}
2020-06-14 18:16:26 +00:00
}
2023-05-13 12:35:46 +00:00
static bool _properties_migrate_settings ( void * priv , obs_properties_t * , obs_property_t * p , obs_data_t * settings ) noexcept
2022-08-27 11:17:47 +00:00
{
try {
obs_property_set_visible ( p , false ) ;
reinterpret_cast < factory_t * > ( priv ) - > _migrate ( settings , nullptr ) ;
return true ;
} catch ( const std : : exception & ex ) {
DLOG_ERROR ( " Unexpected exception in function '%s': %s. " , __FUNCTION_NAME__ , ex . what ( ) ) ;
return false ;
} catch ( . . . ) {
DLOG_ERROR ( " Unexpected exception in function '%s'. " , __FUNCTION_NAME__ ) ;
return false ;
}
2021-12-02 15:57:48 +00:00
}
2020-06-14 18:16:26 +00:00
static obs_properties_t * _get_properties2 ( void * data , void * type_data ) noexcept
2022-08-27 11:17:47 +00:00
{
try {
if ( type_data ) {
2023-05-13 12:35:46 +00:00
auto props = reinterpret_cast < factory_t * > ( type_data ) - > get_properties2 ( reinterpret_cast < instance_t * > ( data ) ) ;
2022-08-27 11:17:47 +00:00
{ // Support for permanent settings migration.
2023-05-13 12:35:46 +00:00
auto p = obs_properties_add_int ( props , S_VERSION , " If you can see this, something went horribly wrong. " , std : : numeric_limits < int32_t > : : lowest ( ) , std : : numeric_limits < int32_t > : : max ( ) , 1 ) ;
2022-08-27 11:17:47 +00:00
obs_property_set_modified_callback2 ( p , _properties_migrate_settings , type_data ) ;
}
return props ;
2021-12-02 15:57:48 +00:00
}
2022-08-27 11:17:47 +00:00
return nullptr ;
} catch ( const std : : exception & ex ) {
DLOG_ERROR ( " Unexpected exception in function '%s': %s. " , __FUNCTION_NAME__ , ex . what ( ) ) ;
return nullptr ;
} catch ( . . . ) {
DLOG_ERROR ( " Unexpected exception in function '%s'. " , __FUNCTION_NAME__ ) ;
return nullptr ;
2021-12-02 15:57:48 +00:00
}
2020-06-14 18:16:26 +00:00
}
private /* Instance */ :
static void _destroy ( void * data ) noexcept
2022-08-27 11:17:47 +00:00
{
try {
if ( data )
delete reinterpret_cast < instance_t * > ( data ) ;
} catch ( const std : : exception & ex ) {
DLOG_ERROR ( " Unexpected exception in function '%s': %s. " , __FUNCTION_NAME__ , ex . what ( ) ) ;
} catch ( . . . ) {
DLOG_ERROR ( " Unexpected exception in function '%s'. " , __FUNCTION_NAME__ ) ;
}
2020-06-14 18:16:26 +00:00
}
static bool _update ( void * data , obs_data_t * settings ) noexcept
2022-08-27 11:17:47 +00:00
{
try {
auto priv = reinterpret_cast < encoder_instance * > ( data ) ;
if ( priv ) {
reinterpret_cast < factory_t * > ( obs_encoder_get_type_data ( priv - > get ( ) ) ) - > _migrate ( settings , priv ) ;
return priv - > update ( settings ) ;
}
return false ;
} catch ( const std : : exception & ex ) {
DLOG_ERROR ( " Unexpected exception in function '%s': %s. " , __FUNCTION_NAME__ , ex . what ( ) ) ;
return false ;
} catch ( . . . ) {
DLOG_ERROR ( " Unexpected exception in function '%s'. " , __FUNCTION_NAME__ ) ;
return false ;
2020-06-14 18:16:26 +00:00
}
}
2023-05-13 12:35:46 +00:00
static bool _encode ( void * data , struct encoder_frame * frame , struct encoder_packet * packet , bool * received_packet ) noexcept
2022-08-27 11:17:47 +00:00
{
try {
if ( data )
return reinterpret_cast < encoder_instance * > ( data ) - > encode_video ( frame , packet , received_packet ) ;
return false ;
} catch ( const std : : exception & ex ) {
DLOG_ERROR ( " Unexpected exception in function '%s': %s. " , __FUNCTION_NAME__ , ex . what ( ) ) ;
return false ;
} catch ( . . . ) {
DLOG_ERROR ( " Unexpected exception in function '%s'. " , __FUNCTION_NAME__ ) ;
return false ;
}
2020-06-14 18:16:26 +00:00
}
2023-05-13 12:35:46 +00:00
static bool _encode_texture ( void * data , uint32_t handle , int64_t pts , uint64_t lock_key , uint64_t * next_key , struct encoder_packet * packet , bool * received_packet ) noexcept
2022-08-27 11:17:47 +00:00
{
try {
if ( data )
2023-05-13 12:35:46 +00:00
return reinterpret_cast < encoder_instance * > ( data ) - > encode_video ( handle , pts , lock_key , next_key , packet , received_packet ) ;
2022-08-27 11:17:47 +00:00
return false ;
} catch ( const std : : exception & ex ) {
DLOG_ERROR ( " Unexpected exception in function '%s': %s. " , __FUNCTION_NAME__ , ex . what ( ) ) ;
return false ;
} catch ( . . . ) {
DLOG_ERROR ( " Unexpected exception in function '%s'. " , __FUNCTION_NAME__ ) ;
return false ;
}
2020-06-14 18:16:26 +00:00
}
static size_t _get_frame_size ( void * data ) noexcept
2022-08-27 11:17:47 +00:00
{
try {
if ( data )
return reinterpret_cast < encoder_instance * > ( data ) - > get_frame_size ( ) ;
return 0 ;
} catch ( const std : : exception & ex ) {
DLOG_ERROR ( " Unexpected exception in function '%s': %s. " , __FUNCTION_NAME__ , ex . what ( ) ) ;
return 0 ;
} catch ( . . . ) {
DLOG_ERROR ( " Unexpected exception in function '%s'. " , __FUNCTION_NAME__ ) ;
return 0 ;
}
2020-06-14 18:16:26 +00:00
}
static bool _get_extra_data ( void * data , uint8_t * * extra_data , size_t * size ) noexcept
2022-08-27 11:17:47 +00:00
{
try {
if ( data )
return reinterpret_cast < encoder_instance * > ( data ) - > get_extra_data ( extra_data , size ) ;
return false ;
} catch ( const std : : exception & ex ) {
DLOG_ERROR ( " Unexpected exception in function '%s': %s. " , __FUNCTION_NAME__ , ex . what ( ) ) ;
return false ;
} catch ( . . . ) {
DLOG_ERROR ( " Unexpected exception in function '%s'. " , __FUNCTION_NAME__ ) ;
return false ;
}
2020-06-14 18:16:26 +00:00
}
static bool _get_sei_data ( void * data , uint8_t * * sei_data , size_t * size ) noexcept
2022-08-27 11:17:47 +00:00
{
try {
if ( data )
return reinterpret_cast < encoder_instance * > ( data ) - > get_sei_data ( sei_data , size ) ;
return false ;
} catch ( const std : : exception & ex ) {
DLOG_ERROR ( " Unexpected exception in function '%s': %s. " , __FUNCTION_NAME__ , ex . what ( ) ) ;
return false ;
} catch ( . . . ) {
DLOG_ERROR ( " Unexpected exception in function '%s'. " , __FUNCTION_NAME__ ) ;
return false ;
}
2020-06-14 18:16:26 +00:00
}
static void _get_audio_info ( void * data , struct audio_convert_info * info ) noexcept
2022-08-27 11:17:47 +00:00
{
try {
if ( data )
reinterpret_cast < encoder_instance * > ( data ) - > get_audio_info ( info ) ;
} catch ( const std : : exception & ex ) {
DLOG_ERROR ( " Unexpected exception in function '%s': %s. " , __FUNCTION_NAME__ , ex . what ( ) ) ;
} catch ( . . . ) {
DLOG_ERROR ( " Unexpected exception in function '%s'. " , __FUNCTION_NAME__ ) ;
}
2020-06-14 18:16:26 +00:00
}
static void _get_video_info ( void * data , struct video_scale_info * info ) noexcept
2022-08-27 11:17:47 +00:00
{
try {
if ( data )
reinterpret_cast < encoder_instance * > ( data ) - > get_video_info ( info ) ;
} catch ( const std : : exception & ex ) {
DLOG_ERROR ( " Unexpected exception in function '%s': %s. " , __FUNCTION_NAME__ , ex . what ( ) ) ;
} catch ( . . . ) {
DLOG_ERROR ( " Unexpected exception in function '%s'. " , __FUNCTION_NAME__ ) ;
}
2020-06-14 18:16:26 +00:00
}
public :
virtual const char * get_name ( )
{
return " Not Yet Implemented " ;
}
2020-07-27 17:44:27 +00:00
virtual void * create ( obs_data_t * settings , obs_encoder_t * encoder , bool is_hw )
2020-06-14 18:16:26 +00:00
{
2020-07-27 17:44:27 +00:00
return reinterpret_cast < void * > ( new instance_t ( settings , encoder , is_hw ) ) ;
2020-06-14 18:16:26 +00:00
}
virtual void get_defaults2 ( obs_data_t * data ) { }
2021-12-02 15:57:48 +00:00
virtual void migrate ( obs_data_t * data , uint64_t version ) { }
2020-06-14 18:16:26 +00:00
virtual obs_properties_t * get_properties2 ( instance_t * data )
{
return nullptr ;
}
} ;
2021-06-08 02:36:30 +00:00
} // namespace streamfx::obs