فهرست منبع

Fix video reset and apply new video settings

This allows the changing of bideo settings without having to completely
reset all graphics data.  Will recreate internal output/conversion
buffers and such and reset the main preview.
jp9000 11 سال پیش
والد
کامیت
0ff0d32731

+ 1 - 0
build/data/obs-studio/locale/en.txt

@@ -56,6 +56,7 @@ Settings.Video.FPS.Numerator="Numerator:"
 Settings.Video.FPS.Denominator="Denominator:"
 Settings.Video.Renderer="Renderer:"
 Settings.Video.InvalidResolution="Invalid resolution value.  Must be [width]x[height] (i.e. 1920x1080)"
+Settings.Video.CurrentlyActive="Video output is currently active.  Please turn off any outputs to change video settings."
 
 Settings.Audio="Audio"
 Settings.Audio.DesktopAudioDevice1="Desktop Audio Device 1:"

+ 6 - 0
libobs/media-io/audio-io.c

@@ -666,6 +666,12 @@ void audio_line_destroy(struct audio_line *line)
 	}
 }
 
+bool audio_output_active(audio_t audio)
+{
+	if (!audio) return false;
+	return audio->inputs.num != 0;
+}
+
 size_t audio_output_blocksize(audio_t audio)
 {
 	return audio->block_size;

+ 2 - 0
libobs/media-io/audio-io.h

@@ -172,6 +172,8 @@ EXPORT void audio_output_disconnect(audio_t video,
 		void (*callback)(void *param, const struct audio_data *data),
 		void *param);
 
+EXPORT bool audio_output_active(audio_t audio);
+
 EXPORT size_t audio_output_blocksize(audio_t audio);
 EXPORT size_t audio_output_planes(audio_t audio);
 EXPORT size_t audio_output_channels(audio_t audio);

+ 6 - 0
libobs/media-io/video-io.c

@@ -308,6 +308,12 @@ void video_output_disconnect(video_t video,
 	pthread_mutex_unlock(&video->input_mutex);
 }
 
+bool video_output_active(video_t video)
+{
+	if (!video) return false;
+	return video->inputs.num != 0;
+}
+
 const struct video_output_info *video_output_getinfo(video_t video)
 {
 	return &video->info;

+ 2 - 0
libobs/media-io/video-io.h

@@ -118,6 +118,8 @@ EXPORT void video_output_disconnect(video_t video,
 		void (*callback)(void *param, const struct video_data *frame),
 		void *param);
 
+EXPORT bool video_output_active(video_t video);
+
 EXPORT const struct video_output_info *video_output_getinfo(video_t video);
 EXPORT void video_output_swap_frame(video_t video, struct video_data *frame);
 EXPORT bool video_output_wait(video_t video);

+ 7 - 7
libobs/obs-source.c

@@ -1,5 +1,5 @@
 /******************************************************************************
-    Copyright (C) 2013 by Hugh Bailey <[email protected]>
+    Copyright (C) 2013-2014 by Hugh Bailey <[email protected]>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -183,7 +183,7 @@ void source_frame_init(struct source_frame *frame, enum video_format format,
 	}
 }
 
-static void obs_source_destroy(obs_source_t source)
+static void obs_source_destroy(struct obs_source *source)
 {
 	size_t i;
 
@@ -950,7 +950,7 @@ static void process_audio(obs_source_t source, const struct source_audio *audio)
 void obs_source_output_audio(obs_source_t source,
 		const struct source_audio *audio)
 {
-	uint32_t flags = obs_source_get_output_flags(source);
+	uint32_t flags = source->info.output_flags;
 	struct filtered_audio *output;
 
 	process_audio(source, audio);
@@ -959,13 +959,13 @@ void obs_source_output_audio(obs_source_t source,
 	output = filter_async_audio(source, &source->audio_data);
 
 	if (output) {
-		bool async = (flags & OBS_SOURCE_ASYNC_VIDEO) == 0;
+		bool async = (flags & OBS_SOURCE_ASYNC_VIDEO) != 0;
 
 		pthread_mutex_lock(&source->audio_mutex);
 
 		/* wait for video to start before outputting any audio so we
 		 * have a base for sync */
-		if (source->timing_set || async) {
+		if (source->timing_set || !async) {
 			struct audio_data data;
 
 			for (int i = 0; i < MAX_AV_PLANES; i++)
@@ -1143,8 +1143,8 @@ void obs_source_process_filter(obs_source_t filter, effect_t effect,
 {
 	obs_source_t target       = obs_filter_gettarget(filter);
 	obs_source_t parent       = obs_filter_getparent(filter);
-	uint32_t     target_flags = obs_source_get_output_flags(target);
-	uint32_t     parent_flags = obs_source_get_output_flags(parent);
+	uint32_t     target_flags = target->info.output_flags;
+	uint32_t     parent_flags = parent->info.output_flags;
 	int          cx           = obs_source_getwidth(target);
 	int          cy           = obs_source_getheight(target);
 	bool         use_matrix   = !!(target_flags & OBS_SOURCE_COLOR_MATRIX);

+ 48 - 21
libobs/obs.c

@@ -168,12 +168,6 @@ static bool obs_init_graphics(struct obs_video_info *ovi)
 	int errorcode;
 
 	make_gs_init_data(&graphics_data, ovi);
-	video->base_width    = ovi->base_width;
-	video->base_height   = ovi->base_height;
-	video->output_width  = ovi->output_width;
-	video->output_height = ovi->output_height;
-
-	video->gpu_conversion = ovi->gpu_conversion;
 
 	errorcode = gs_create(&video->graphics, ovi->graphics_module,
 			&graphics_data);
@@ -186,11 +180,6 @@ static bool obs_init_graphics(struct obs_video_info *ovi)
 
 	gs_entercontext(video->graphics);
 
-	if (ovi->gpu_conversion && !obs_init_gpu_conversion(ovi))
-		success = false;
-	if (success && !obs_init_textures(ovi))
-		success = false;
-
 	if (success) {
 		char *filename = find_libobs_data_file("default.effect");
 		video->default_effect = gs_create_effect_from_file(filename,
@@ -219,6 +208,12 @@ static bool obs_init_video(struct obs_video_info *ovi)
 	int errorcode;
 
 	make_video_info(&vi, ovi);
+	video->base_width     = ovi->base_width;
+	video->base_height    = ovi->base_height;
+	video->output_width   = ovi->output_width;
+	video->output_height  = ovi->output_height;
+	video->gpu_conversion = ovi->gpu_conversion;
+
 	errorcode = video_output_open(&video->video, &vi);
 
 	if (errorcode != VIDEO_OUTPUT_SUCCESS) {
@@ -236,6 +231,15 @@ static bool obs_init_video(struct obs_video_info *ovi)
 	video->main_display.cx = ovi->window_width;
 	video->main_display.cy = ovi->window_height;
 
+	gs_entercontext(video->graphics);
+
+	if (ovi->gpu_conversion && !obs_init_gpu_conversion(ovi))
+		return false;
+	if (!obs_init_textures(ovi))
+		return false;
+
+	gs_leavecontext();
+
 	errorcode = pthread_create(&video->video_thread, NULL,
 			obs_video_thread, obs);
 	if (errorcode != 0)
@@ -268,21 +272,18 @@ static void obs_free_video(void)
 		obs_display_free(&video->main_display);
 		video_output_close(video->video);
 		video->video = NULL;
-	}
-}
 
-static void obs_free_graphics(void)
-{
-	struct obs_core_video *video = &obs->video;
-	size_t i;
+		if (!video->graphics)
+			return;
 
-	if (video->graphics) {
 		gs_entercontext(video->graphics);
 
-		if (video->mapped_surface)
+		if (video->mapped_surface) {
 			stagesurface_unmap(video->mapped_surface);
+			video->mapped_surface = NULL;
+		}
 
-		for (i = 0; i < NUM_TEXTURES; i++) {
+		for (size_t i = 0; i < NUM_TEXTURES; i++) {
 			stagesurface_destroy(video->copy_surfaces[i]);
 			texture_destroy(video->render_textures[i]);
 			texture_destroy(video->convert_textures[i]);
@@ -295,6 +296,19 @@ static void obs_free_graphics(void)
 			video->output_textures[i]  = NULL;
 		}
 
+		gs_leavecontext();
+
+		video->cur_texture = 0;
+	}
+}
+
+static void obs_free_graphics(void)
+{
+	struct obs_core_video *video = &obs->video;
+
+	if (video->graphics) {
+		gs_entercontext(video->graphics);
+
 		effect_destroy(video->default_effect);
 		effect_destroy(video->conversion_effect);
 		video->default_effect = NULL;
@@ -303,7 +317,6 @@ static void obs_free_graphics(void)
 
 		gs_destroy(video->graphics);
 		video->graphics = NULL;
-		video->cur_texture = 0;
 	}
 }
 
@@ -467,11 +480,19 @@ bool obs_initialized(void)
 
 bool obs_reset_video(struct obs_video_info *ovi)
 {
+	if (!obs) return false;
+
+	/* don't allow changing of video settings if active. */
+	if (obs->video.video && video_output_active(obs->video.video))
+		return false;
+
 	struct obs_core_video *video = &obs->video;
 
+	/* align to multiple-of-two and SSE alignment sizes */
 	ovi->output_width  &= 0xFFFFFFFC;
 	ovi->output_height &= 0xFFFFFFFE;
 
+	stop_video();
 	obs_free_video();
 
 	if (!ovi) {
@@ -487,6 +508,12 @@ bool obs_reset_video(struct obs_video_info *ovi)
 
 bool obs_reset_audio(struct audio_output_info *ai)
 {
+	if (!obs) return false;
+
+	/* don't allow changing of audio settings if active. */
+	if (obs->audio.audio && audio_output_active(obs->audio.audio))
+		return false;
+
 	obs_free_audio();
 	if(!ai)
 		return true;

+ 4 - 1
obs/forms/OBSBasicSettings.ui

@@ -495,7 +495,7 @@
           </widget>
          </item>
          <item row="6" column="1">
-          <widget class="QLabel" name="errorText">
+          <widget class="QLabel" name="videoMsg">
            <property name="sizePolicy">
             <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
              <horstretch>0</horstretch>
@@ -508,6 +508,9 @@
            <property name="text">
             <string notr="true"/>
            </property>
+           <property name="wordWrap">
+            <bool>true</bool>
+           </property>
           </widget>
          </item>
         </layout>

+ 10 - 8
obs/window-basic-main.cpp

@@ -51,13 +51,11 @@ void OBSBasic::OBSInit()
 
 	if (!obs_startup())
 		throw "Failed to initialize libobs";
-	if (!InitGraphics())
-		throw "Failed to initialize graphics";
-	if (!InitAudio())
+	if (!ResetVideo())
+		throw "Failed to initialize video";
+	if (!ResetAudio())
 		throw "Failed to initialize audio";
 
-	obs_add_draw_callback(OBSBasic::RenderMain, this);
-
 	signal_handler_connect(obs_signalhandler(), "source-add",
 			OBSBasic::SourceAdded, this);
 	signal_handler_connect(obs_signalhandler(), "source-remove",
@@ -278,7 +276,7 @@ void OBSBasic::RenderMain(void *data, uint32_t cx, uint32_t cy)
 
 /* Main class functions */
 
-bool OBSBasic::InitGraphics()
+bool OBSBasic::ResetVideo()
 {
 	struct obs_video_info ovi;
 
@@ -306,10 +304,14 @@ bool OBSBasic::InitGraphics()
 	ovi.window_width  = size.width();
 	ovi.window_height = size.height();
 
-	return obs_reset_video(&ovi);
+	if (!obs_reset_video(&ovi))
+		return false;
+
+	obs_add_draw_callback(OBSBasic::RenderMain, this);
+	return true;
 }
 
-bool OBSBasic::InitAudio()
+bool OBSBasic::ResetAudio()
 {
 	/* TODO: load audio settings from config */
 	struct audio_output_info ai;

+ 3 - 2
obs/window-basic-main.hpp

@@ -60,8 +60,9 @@ private:
 	void AddSource(obs_scene_t scene, const char *id);
 	void AddSourcePopupMenu(const QPoint &pos);
 
-	bool InitGraphics();
-	bool InitAudio();
+public:
+	bool ResetVideo();
+	bool ResetAudio();
 
 	void NewProject();
 	void SaveProject();

+ 16 - 4
obs/window-basic-settings.cpp

@@ -15,6 +15,7 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
 
+#include <obs.hpp>
 #include <util/util.hpp>
 #include <util/lexer.h>
 #include <sstream>
@@ -25,6 +26,7 @@
 #include "obs-app.hpp"
 #include "platform.hpp"
 #include "qt-wrappers.hpp"
+#include "window-basic-main.hpp"
 #include "window-basic-settings.hpp"
 
 #include <util/platform.h>
@@ -205,6 +207,8 @@ void OBSBasicSettings::LoadResolutionLists()
 
 	ResetDownscales(cx, cy);
 
+	ui->baseResolution->lineEdit()->setText(ResString(cx, cy).c_str());
+
 	cx = config_get_uint(GetGlobalConfig(), "Video", "OutputCX");
 	cy = config_get_uint(GetGlobalConfig(), "Video", "OutputCY");
 
@@ -254,6 +258,11 @@ void OBSBasicSettings::LoadVideoSettings()
 {
 	loading = true;
 
+	if (video_output_active(obs_video())) {
+		ui->videoPage->setEnabled(false);
+		ui->videoMsg->setText(QTStr("Settings.Video.CurrentlyActive"));
+	}
+
 	LoadRendererList();
 	LoadResolutionLists();
 	LoadFPSData();
@@ -316,6 +325,10 @@ void OBSBasicSettings::SaveVideoSettings()
 	config_set_uint(GetGlobalConfig(), "Video", "FPSInt", fpsInteger);
 	config_set_uint(GetGlobalConfig(), "Video", "FPSNum", fpsNumerator);
 	config_set_uint(GetGlobalConfig(), "Video", "FPSDen", fpsDenominator);
+
+	OBSBasic *window = qobject_cast<OBSBasic*>(parent());
+	if (window)
+		window->ResetVideo();
 }
 
 void OBSBasicSettings::SaveSettings()
@@ -400,12 +413,12 @@ static bool ValidResolutions(Ui::OBSBasicSettings *ui)
 	if (!ConvertResText(QT_TO_UTF8(baseRes), cx, cy) ||
 	    !ConvertResText(QT_TO_UTF8(outputRes), cx, cy)) {
 
-		ui->errorText->setText(
+		ui->videoMsg->setText(
 				QTStr("Settings.Video.InvalidResolution"));
 		return false;
 	}
 
-	ui->errorText->setText("");
+	ui->videoMsg->setText("");
 	return true;
 }
 
@@ -421,8 +434,7 @@ void OBSBasicSettings::on_renderer_currentIndexChanged(int index)
 {
 	if (!loading) {
 		videoChanged = true;
-		ui->errorText->setText(
-				QTStr("Settings.ProgramRestart"));
+		ui->videoMsg->setText(QTStr("Settings.ProgramRestart"));
 	}
 
 	UNUSED_PARAMETER(index);