|
16 | 16 | #include <QUrl> |
17 | 17 | #include <QUrlQuery> |
18 | 18 |
|
| 19 | +#include <algorithm> |
19 | 20 | #include <cinttypes> |
20 | 21 |
|
21 | 22 | // Codec profile strings |
@@ -238,7 +239,14 @@ static OBSEncoderAutoRelease create_video_encoder(DStr &name_buffer, size_t enco |
238 | 239 |
|
239 | 240 | dstr_printf(name_buffer, "multitrack video video encoder %zu", encoder_index); |
240 | 241 |
|
241 | | - OBSDataAutoRelease encoder_settings = obs_data_create_from_json(encoder_config.settings.dump().c_str()); |
| 242 | + // settings.dump() produces "null" when the config omits encoder settings, which |
| 243 | + // obs_data_create_from_json cannot parse. Fall back to empty settings so the encoder uses its defaults. |
| 244 | + OBSDataAutoRelease encoder_settings = |
| 245 | + encoder_config.settings.is_object() ? obs_data_create_from_json(encoder_config.settings.dump().c_str()) |
| 246 | + : obs_data_create(); |
| 247 | + if (!encoder_config.settings.is_object()) { |
| 248 | + blog(LOG_INFO, "Encoder %zu has no settings, using defaults", encoder_index); |
| 249 | + } |
242 | 250 |
|
243 | 251 | /* VAAPI-based encoders unfortunately use an integer for "profile". Until a string-based "profile" can be used with |
244 | 252 | * VAAPI, find the corresponding integer value and update the settings with an integer-based "profile". |
@@ -613,10 +621,11 @@ static bool create_video_encoders(const GoLiveApi::Config &go_live_config, |
613 | 621 | obs_output_set_video_encoder2(recording_output, encoder, i); |
614 | 622 |
|
615 | 623 | auto &data = go_live_config.encoder_configurations[i].bitrate_interpolation_points; |
616 | | - if (data.has_value()) |
| 624 | + if (data.has_value()) { |
617 | 625 | bitrate_interpolation_array.push_back(*data); |
618 | | - else |
| 626 | + } else { |
619 | 627 | bitrate_interpolation_array.push_back(json::array()); |
| 628 | + } |
620 | 629 | } |
621 | 630 |
|
622 | 631 | video_encoder_group = encoder_group; |
@@ -675,7 +684,15 @@ static void create_audio_encoders(const GoLiveApi::Config &go_live_config, |
675 | 684 |
|
676 | 685 | for (size_t i = 0; i < configs.size(); i++) { |
677 | 686 | dstr_printf(encoder_name_buffer, "%s %zu", name_prefix, i); |
678 | | - OBSDataAutoRelease settings = obs_data_create_from_json(configs[i].settings.dump().c_str()); |
| 687 | + // settings.dump() produces "null" when the config omits encoder settings, |
| 688 | + // which obs_data_create_from_json cannot parse. Fall back to empty settings. |
| 689 | + OBSDataAutoRelease settings = |
| 690 | + configs[i].settings.is_object() |
| 691 | + ? obs_data_create_from_json(configs[i].settings.dump().c_str()) |
| 692 | + : obs_data_create(); |
| 693 | + if (!configs[i].settings.is_object()) { |
| 694 | + blog(LOG_INFO, "Audio encoder %zu has no settings, using defaults", i); |
| 695 | + } |
679 | 696 | OBSEncoderAutoRelease audio_encoder = |
680 | 697 | create_audio_encoder(encoder_name_buffer->array, audio_encoder_id, settings, mixer_idx); |
681 | 698 |
|
@@ -782,7 +799,18 @@ static OBSOutputs SetupOBSOutput(QWidget *parent, const QString &multitrack_vide |
782 | 799 | return {nullptr, nullptr}; |
783 | 800 |
|
784 | 801 | OBSDataAutoRelease settings = obs_output_get_settings(output); |
785 | | - obs_data_set_string(settings, "interpolation_table_data", bitrate_interpolation_array.dump().c_str()); |
| 802 | + // Only set interpolation_table_data if every encoder has interpolation points. Partial data would |
| 803 | + // fail validation in the output plugin and disable DBR. Omitting it lets the output use its default |
| 804 | + // linear interpolation (proportional scaling from 0 to max bitrate). |
| 805 | + bool has_interpolation_data = std::all_of(bitrate_interpolation_array.begin(), |
| 806 | + bitrate_interpolation_array.end(), |
| 807 | + [](const json &arr) { return !arr.empty(); }); |
| 808 | + if (has_interpolation_data) { |
| 809 | + obs_data_set_string(settings, "interpolation_table_data", bitrate_interpolation_array.dump().c_str()); |
| 810 | + } else { |
| 811 | + blog(LOG_INFO, |
| 812 | + "Interpolation data missing for one or more encoders, using default linear interpolation"); |
| 813 | + } |
786 | 814 | obs_output_update(output, settings); |
787 | 815 |
|
788 | 816 | std::vector<speaker_layout> requested_speaker_layouts; |
|
0 commit comments