encoders/generic: Replace generated UI with the new UI Handlers

This commit is contained in:
Michael Fabian 'Xaymar' Dirks
2019-07-07 13:43:02 +02:00
parent 8fb69d6870
commit b442914ebe
+27 -223
View File
@@ -287,44 +287,14 @@ const char* encoder::generic_factory::get_name()
void encoder::generic_factory::get_defaults(obs_data_t* settings)
{
#ifdef GENERATE_OPTIONS
AVCodecContext* ctx = avcodec_alloc_context3(this->avcodec_ptr);
if (ctx->priv_data) {
const AVOption* opt = nullptr;
while ((opt = av_opt_next(ctx->priv_data, opt)) != nullptr) {
if (opt->type == AV_OPT_TYPE_CONST && opt->unit != nullptr) {
continue;
}
switch (opt->type) {
case AV_OPT_TYPE_BOOL:
obs_data_set_default_bool(settings, opt->name, !!opt->default_val.i64);
break;
case AV_OPT_TYPE_INT:
case AV_OPT_TYPE_INT64:
case AV_OPT_TYPE_UINT64:
obs_data_set_default_int(settings, opt->name, opt->default_val.i64);
break;
case AV_OPT_TYPE_FLOAT:
case AV_OPT_TYPE_DOUBLE:
obs_data_set_default_double(settings, opt->name, opt->default_val.dbl);
break;
case AV_OPT_TYPE_STRING:
obs_data_set_default_string(settings, opt->name, opt->default_val.str);
break;
}
{ // Handler
auto ptr = obsffmpeg::find_codec_handler(this->avcodec_ptr->name);
if (ptr) {
ptr->get_defaults(settings, this->avcodec_ptr, nullptr);
}
}
#endif
{ // Integrated Options
// Rate Control
obs_data_set_default_int(settings, P_RATECONTROL_PROFILE, 0);
obs_data_set_default_int(settings, P_RATECONTROL_BITRATE, 2500);
obs_data_set_default_int(settings, P_RATECONTROL_KEYFRAME_TYPE, 0);
obs_data_set_default_double(settings, P_RATECONTROL_KEYFRAME_INTERVAL ".Seconds", 2.0);
obs_data_set_default_int(settings, P_RATECONTROL_KEYFRAME_INTERVAL ".Frames", 300);
// FFmpeg
obs_data_set_default_string(settings, P_FFMPEG_CUSTOMSETTINGS, "");
obs_data_set_default_int(settings, P_FFMPEG_STANDARDCOMPLIANCE, FF_COMPLIANCE_STRICT);
@@ -333,158 +303,13 @@ void encoder::generic_factory::get_defaults(obs_data_t* settings)
void encoder::generic_factory::get_properties(obs_properties_t* props)
{
#ifdef GENERATE_OPTIONS
// Encoder Options
AVCodecContext* ctx = avcodec_alloc_context3(this->avcodec_ptr);
if (ctx->priv_data) {
std::map<std::string, std::pair<obs_property_t*, const AVOption*>> unit_property_map;
const AVOption* opt = nullptr;
while ((opt = av_opt_next(ctx->priv_data, opt)) != nullptr) {
obs_property_t* p = nullptr;
// Constants are parts of a unit, not actual options.
if (opt->type == AV_OPT_TYPE_CONST) {
auto unit = unit_property_map.find(opt->unit);
if (unit == unit_property_map.end()) {
continue;
}
switch (unit->second.second->type) {
case AV_OPT_TYPE_INT:
case AV_OPT_TYPE_INT64:
obs_property_list_add_int(unit->second.first, opt->name, opt->default_val.i64);
break;
case AV_OPT_TYPE_FLOAT:
case AV_OPT_TYPE_DOUBLE:
obs_property_list_add_float(unit->second.first, opt->name,
opt->default_val.dbl);
break;
case AV_OPT_TYPE_STRING:
obs_property_list_add_string(unit->second.first, opt->name,
opt->default_val.str);
break;
default:
throw std::runtime_error("unhandled const type");
}
continue;
}
switch (opt->type) {
case AV_OPT_TYPE_BOOL:
p = obs_properties_add_bool(props, opt->name, opt->name);
break;
case AV_OPT_TYPE_INT:
case AV_OPT_TYPE_INT64:
case AV_OPT_TYPE_UINT64:
if (opt->unit != nullptr) {
p = obs_properties_add_list(props, opt->name, opt->name, OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_INT);
unit_property_map.emplace(opt->unit,
std::pair<obs_property_t*, const AVOption*>{p, opt});
} else {
p = obs_properties_add_int(props, opt->name, opt->name,
static_cast<int>(opt->min),
static_cast<int>(opt->max), 1);
}
break;
case AV_OPT_TYPE_FLOAT:
case AV_OPT_TYPE_DOUBLE:
if (opt->unit != nullptr) {
p = obs_properties_add_list(props, opt->name, opt->name, OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_FLOAT);
unit_property_map.emplace(opt->unit,
std::pair<obs_property_t*, const AVOption*>{p, opt});
} else {
p = obs_properties_add_float(props, opt->name, opt->name, opt->min, opt->max,
0.01);
}
break;
case AV_OPT_TYPE_STRING:
if (opt->unit != nullptr) {
p = obs_properties_add_list(props, opt->name, opt->name, OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_STRING);
unit_property_map.emplace(opt->unit,
std::pair<obs_property_t*, const AVOption*>{p, opt});
} else {
p = obs_properties_add_text(props, opt->name, opt->name,
obs_text_type::OBS_TEXT_DEFAULT);
}
break;
case AV_OPT_TYPE_FLAGS:
case AV_OPT_TYPE_RATIONAL:
case AV_OPT_TYPE_VIDEO_RATE:
case AV_OPT_TYPE_BINARY:
case AV_OPT_TYPE_DICT:
case AV_OPT_TYPE_IMAGE_SIZE:
case AV_OPT_TYPE_PIXEL_FMT:
case AV_OPT_TYPE_SAMPLE_FMT:
case AV_OPT_TYPE_DURATION:
case AV_OPT_TYPE_COLOR:
case AV_OPT_TYPE_CHANNEL_LAYOUT:
PLOG_WARNING("Skipped option '%s' for codec '%s' as option type is not supported.",
opt->name, this->info.uid.c_str());
break;
}
if ((opt->flags & AV_OPT_FLAG_READONLY) && (p != nullptr)) {
obs_property_set_enabled(p, false);
}
{ // Handler
auto ptr = obsffmpeg::find_codec_handler(this->avcodec_ptr->name);
if (ptr) {
ptr->get_properties(props, this->avcodec_ptr, nullptr);
}
}
avcodec_free_context(&ctx);
#endif
// FFmpeg Options
{ /// Rate Control
auto prs = obs_properties_create();
{
auto grp = obs_properties_create();
auto p1 = obs_properties_add_list(grp, P_RATECONTROL_KEYFRAME_TYPE,
TRANSLATE(P_RATECONTROL_KEYFRAME_TYPE), OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_INT);
obs_property_set_long_description(p1, TRANSLATE(DESC(P_RATECONTROL_KEYFRAME_TYPE)));
obs_property_set_modified_callback2(p1, modified_ratecontrol_properties, this);
obs_property_list_add_int(p1, TRANSLATE(P_RATECONTROL_KEYFRAME_TYPE ".Seconds"),
static_cast<int64_t>(keyframe_type::Seconds));
obs_property_list_add_int(p1, TRANSLATE(P_RATECONTROL_KEYFRAME_TYPE ".Frames"),
static_cast<int64_t>(keyframe_type::Frames));
auto p2 = obs_properties_add_float(grp, P_RATECONTROL_KEYFRAME_INTERVAL ".Seconds",
TRANSLATE(P_RATECONTROL_KEYFRAME_INTERVAL), 0.0,
std::numeric_limits<double_t>::max(), 0.01);
obs_property_set_long_description(p2, TRANSLATE(DESC(P_RATECONTROL_KEYFRAME_INTERVAL)));
auto p3 = obs_properties_add_int(grp, P_RATECONTROL_KEYFRAME_INTERVAL ".Frames",
TRANSLATE(P_RATECONTROL_KEYFRAME_INTERVAL), 0,
std::numeric_limits<int32_t>::max(), 1);
obs_property_set_long_description(p3, TRANSLATE(DESC(P_RATECONTROL_KEYFRAME_INTERVAL)));
auto gp = obs_properties_add_group(prs, P_RATECONTROL_KEYFRAME,
TRANSLATE(P_RATECONTROL_KEYFRAME), OBS_GROUP_NORMAL, grp);
obs_property_set_visible(gp, !(this->avcodec_ptr->capabilities & AV_CODEC_CAP_INTRA_ONLY));
}
{
auto p = obs_properties_add_int(prs, P_RATECONTROL_BITRATE, TRANSLATE(P_RATECONTROL_BITRATE), 1,
std::numeric_limits<int32_t>::max(), 1);
obs_property_set_long_description(p, TRANSLATE(DESC(P_RATECONTROL_BITRATE)));
}
{
auto p = obs_properties_add_list(prs, P_RATECONTROL_PROFILE, TRANSLATE(P_RATECONTROL_PROFILE),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
if (this->avcodec_ptr->profiles) {
auto profile = this->avcodec_ptr->profiles;
obs_property_list_add_int(p, TRANSLATE(P_RATECONTROL_PROFILE ".None"),
FF_PROFILE_UNKNOWN);
while (profile->profile != FF_PROFILE_UNKNOWN) {
obs_property_list_add_int(p, profile->name, profile->profile);
profile++;
}
}
}
obs_properties_add_group(props, P_RATECONTROL, TRANSLATE(P_RATECONTROL), OBS_GROUP_NORMAL, prs);
};
{
auto prs = obs_properties_create();
{
@@ -535,7 +360,7 @@ encoder::generic::generic(obs_data_t* settings, obs_encoder_t* encoder)
this->factory = reinterpret_cast<generic_factory*>(obs_encoder_get_type_data(self));
// Verify that the codec actually still exists.
this->codec = avcodec_find_encoder(this->factory->get_avcodec()->id);
this->codec = avcodec_find_encoder_by_name(this->factory->get_avcodec()->name);
if (!this->codec) {
PLOG_ERROR("Failed to find encoder for codec '%s'.", this->factory->get_avcodec()->name);
throw std::runtime_error("failed to find codec");
@@ -674,51 +499,30 @@ encoder::generic::~generic()
}
}
void encoder::generic::get_properties(obs_properties_t*) {}
void encoder::generic::get_properties(obs_properties_t* props)
{
{ // Handler
auto ptr = obsffmpeg::find_codec_handler(this->codec->name);
if (ptr) {
ptr->get_properties(props, this->codec, this->context);
}
}
}
bool encoder::generic::update(obs_data_t* settings)
{
#ifdef GENERATE_OPTIONS
// Apply UI options.
if (this->context->priv_data) {
const AVOption* opt = nullptr;
while ((opt = av_opt_next(this->context->priv_data, opt)) != nullptr) {
if (opt->type == AV_OPT_TYPE_CONST && opt->unit != nullptr) {
continue;
}
switch (opt->type) {
case AV_OPT_TYPE_BOOL:
av_opt_set_int(this->context->priv_data, opt->name,
obs_data_get_bool(settings, opt->name) ? 1 : 0, 0);
break;
case AV_OPT_TYPE_INT:
case AV_OPT_TYPE_INT64:
case AV_OPT_TYPE_UINT64:
av_opt_set_int(this->context->priv_data, opt->name,
obs_data_get_int(settings, opt->name), 0);
break;
case AV_OPT_TYPE_FLOAT:
case AV_OPT_TYPE_DOUBLE:
av_opt_set_double(this->context->priv_data, opt->name,
obs_data_get_double(settings, opt->name), 0);
break;
case AV_OPT_TYPE_STRING:
av_opt_set(this->context->priv_data, opt->name,
obs_data_get_string(settings, opt->name), 0);
break;
}
{ // Handler
auto ptr = obsffmpeg::find_codec_handler(this->codec->name);
if (ptr) {
ptr->update(settings, this->codec, this->context);
}
}
#endif
// Apply default options
this->context->profile = static_cast<int>(obs_data_get_int(settings, P_RATECONTROL_PROFILE));
this->context->bit_rate = static_cast<int>(obs_data_get_int(settings, P_RATECONTROL_BITRATE));
// Apply custom options.
av_opt_set_from_string(this->context, obs_data_get_string(settings, P_FFMPEG_CUSTOMSETTINGS), nullptr, ";",
"=");
{ // FFmpeg
// Apply custom options.
av_opt_set_from_string(this->context, obs_data_get_string(settings, P_FFMPEG_CUSTOMSETTINGS), nullptr,
";", "=");
}
return false;
}