33#include " common-settings.hpp"
44#include < util/config-file.h>
55
6+ #include < QPair>
7+
68/*
79 We are detecting the stream settings so if they're using a large canvas but
810 already have the rescaler on, they will be streaming correctly.
@@ -32,8 +34,7 @@ void UpdateStreamingResolution(int *resolutionXY, bool isRescaled,
3234};
3335
3436QSharedPointer<StreamWizard::EncoderSettingsRequest>
35- StreamingSettingsUtility::makeEncoderSettingsFromCurrentState (
36- config_t *config, obs_data_t *settings)
37+ StreamingSettingsUtility::makeEncoderSettingsFromCurrentState (config_t *config)
3738{
3839 QSharedPointer<StreamWizard::EncoderSettingsRequest> currentSettings (
3940 new StreamWizard::EncoderSettingsRequest ());
@@ -43,12 +44,6 @@ StreamingSettingsUtility::makeEncoderSettingsFromCurrentState(
4344 currentSettings->videoType = StreamWizard::VideoType::live;
4445 // only live and rmpts is supported for now
4546 currentSettings->protocol = StreamWizard::StreamProtocol::rtmps;
46-
47- currentSettings->serverUrl =
48- bstrdup (obs_data_get_string (settings, " server" ));
49- currentSettings->serviceName =
50- bstrdup (obs_data_get_string (settings, " service" ));
51-
5247 /* Video */
5348 bool isRescaled = config_get_bool (config, " AdvOut" , " Rescale" );
5449 int resolutionXY[2 ] = {0 , 0 };
@@ -73,3 +68,177 @@ StreamingSettingsUtility::makeEncoderSettingsFromCurrentState(
7368
7469 return currentSettings;
7570};
71+
72+ /*
73+ * StreamWizard::SettingsMap is sparse in that it wont have all keys
74+ * as well, the user can opt out of settings being applied.
75+ * The map looks like [ SettingsResponseKeys : QPair<QVariant, bool> ]
76+ * AKA [KEY : SetttingPair<Setting_Value_Variant, User_Wants_Setting_Bool> ]
77+ * if the key is available, it means the wizard provider added a value for it
78+ * but the bool in the QPair is false if the user selected in the wizard not to
79+ * apply the setting. A case would be we suggest a 720p stream but the user
80+ * knows their account supports 1080 so disabled the setting from applying.
81+
82+ * Returns TRUE is map contrains something for the key and it is marked true
83+ */
84+ bool CheckInMapAndSelected (StreamWizard::SettingsMap *map, const char *key)
85+ {
86+ if (!map->contains (key)) {
87+ return false ;
88+ }
89+ const QPair<QVariant, bool > settingPair = map->value (key);
90+ return settingPair.second ;
91+ }
92+
93+ // Helper Functions for ::applyWizardSettings
94+ int intFromMap (StreamWizard::SettingsMap *map, const char *key)
95+ {
96+ QPair<QVariant, bool > settingPair = map->value (key);
97+ QVariant data = settingPair.first ;
98+ return data.toInt ();
99+ }
100+
101+ QString stringFromMap (StreamWizard::SettingsMap *map, const char *key)
102+ {
103+ QPair<QVariant, bool > settingPair = map->value (key);
104+ QVariant data = settingPair.first ;
105+ return data.toString ();
106+ }
107+
108+ double doubleFromMap (StreamWizard::SettingsMap *map, const char *key)
109+ {
110+ QPair<QVariant, bool > settingPair = map->value (key);
111+ QVariant data = settingPair.first ;
112+ return data.toDouble ();
113+ }
114+
115+ bool boolFromMap (StreamWizard::SettingsMap *map, const char *key)
116+ {
117+ QPair<QVariant, bool > settingPair = map->value (key);
118+ QVariant data = settingPair.first ;
119+ return data.toBool ();
120+ }
121+
122+ /*
123+ * Given a settings map [ SettingsResponseKeys : QPair<QVariant, bool> ] apply
124+ * settings that are in the sparse map as well selected by the user (which is
125+ * marked by the bool in the pair).
126+ * Apply to Basic encoder settings.
127+ * Possible later goal: autoconfig advanced settings too
128+ */
129+ void StreamingSettingsUtility::applyWizardSettings (
130+ QSharedPointer<StreamWizard::SettingsMap> newSettings, config_t *config)
131+ {
132+
133+ if (newSettings == nullptr || newSettings.isNull ())
134+ return ;
135+
136+ // scope to function usage
137+ using namespace StreamWizard ;
138+
139+ SettingsMap *map = newSettings.data ();
140+
141+ QStringList x264SettingList;
142+ config_set_bool (config, " SimpleOutput" , " UseAdvanced" , true );
143+
144+ // Resolution must have both
145+ if (CheckInMapAndSelected (map, SettingsResponseKeys.videoHeight ) &&
146+ CheckInMapAndSelected (map, SettingsResponseKeys.videoWidth )) {
147+
148+ int canvasX = intFromMap (map, SettingsResponseKeys.videoWidth );
149+ int canvasY = intFromMap (map, SettingsResponseKeys.videoHeight );
150+ config_set_uint (config, " Video" , " OutputCX" , canvasX);
151+ config_set_uint (config, " Video" , " OutputCY" , canvasY);
152+ }
153+
154+ // TODO: FPS is hacky but covers all integer and standard drop frame cases
155+ if (CheckInMapAndSelected (map, SettingsResponseKeys.framerate )) {
156+ double currentFPS = CommonSettings::GetConfigFPSDouble (config);
157+ double newFPS =
158+ doubleFromMap (map, SettingsResponseKeys.framerate );
159+ if (abs (currentFPS - newFPS) >
160+ 0.001 ) { // Only change if different
161+ if (abs (floor (newFPS) - newFPS) >
162+ 0.01 ) { // Is a drop-frame FPS
163+ int num = ceil (newFPS) * 1000 ;
164+ int den = 1001 ;
165+ config_set_uint (config, " Video" , " FPSType" ,
166+ 2 ); // Fraction
167+ config_set_uint (config, " Video" , " FPSNum" , num);
168+ config_set_uint (config, " Video" , " FPSDen" , den);
169+ } else { // Is integer FPS
170+ config_set_uint (config, " Video" , " FPSType" ,
171+ 1 ); // Integer
172+ config_set_uint (config, " Video" , " FPSInt" ,
173+ (int )floor (newFPS));
174+ }
175+ }
176+ }
177+
178+ if (CheckInMapAndSelected (map, SettingsResponseKeys.videoBitrate )) {
179+ int newBitrate =
180+ intFromMap (map, SettingsResponseKeys.videoBitrate );
181+ config_set_int (config, " SimpleOutput" , " VBitrate" , newBitrate);
182+ }
183+
184+ if (CheckInMapAndSelected (map, SettingsResponseKeys.h264Profile )) {
185+ QString profile =
186+ stringFromMap (map, SettingsResponseKeys.h264Profile );
187+ profile = profile.toLower ();
188+ x264SettingList.append (" profile=" + profile);
189+ }
190+
191+ if (CheckInMapAndSelected (map, SettingsResponseKeys.h264Level )) {
192+ QString levelString =
193+ stringFromMap (map, SettingsResponseKeys.h264Level );
194+ x264SettingList.append (" level=" + levelString);
195+ }
196+
197+ if (CheckInMapAndSelected (map, SettingsResponseKeys.gopSizeInFrames )) {
198+ int gopSize =
199+ intFromMap (map, SettingsResponseKeys.gopSizeInFrames );
200+ x264SettingList.append (" keyint=" + QString::number (gopSize));
201+ }
202+
203+ if (CheckInMapAndSelected (map, SettingsResponseKeys.gopType )) {
204+ QString gopType =
205+ stringFromMap (map, SettingsResponseKeys.gopType );
206+ x264SettingList.append (" slice_mode=" + gopType);
207+ }
208+
209+ if (CheckInMapAndSelected (map, SettingsResponseKeys.gopClosed )) {
210+ bool gopClose =
211+ boolFromMap (map, SettingsResponseKeys.gopClosed );
212+ if (gopClose) {
213+ x264SettingList.append (" open_gop=0" );
214+ } else {
215+ x264SettingList.append (" open_gop=1" );
216+ }
217+ }
218+
219+ if (CheckInMapAndSelected (map, SettingsResponseKeys.gopBFrames )) {
220+ int bFrames = intFromMap (map, SettingsResponseKeys.gopBFrames );
221+ x264SettingList.append (" bframes=" + QString::number (bFrames));
222+ }
223+
224+ if (CheckInMapAndSelected (map, SettingsResponseKeys.gopRefFrames )) {
225+ int refFrames =
226+ intFromMap (map, SettingsResponseKeys.gopRefFrames );
227+ x264SettingList.append (" ref=" + QString::number (refFrames));
228+ }
229+
230+ // SettingsResponseKeys.streamRateControlMode defaults to CBR in Simple
231+ // encoder mode. Can add later for advanced panel.
232+
233+ if (CheckInMapAndSelected (map, SettingsResponseKeys.streamBufferSize )) {
234+ int bufferSize =
235+ intFromMap (map, SettingsResponseKeys.streamBufferSize );
236+ x264SettingList.append (" bufsize=" +
237+ QString::number (bufferSize));
238+ }
239+
240+ QString x264String = x264SettingList.join (" " );
241+ const char *x264_c_String = x264String.toStdString ().c_str ();
242+ config_set_string (config, " SimpleOutput" , " x264Settings" ,
243+ x264_c_String);
244+ };
0 commit comments