diff --git a/build/data/obs-studio/locale/en.txt b/build/data/obs-studio/locale/en.txt index f229bb2a3..db3007f2e 100644 --- a/build/data/obs-studio/locale/en.txt +++ b/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:" diff --git a/libobs/media-io/audio-io.c b/libobs/media-io/audio-io.c index 22550f74c..617af18fc 100644 --- a/libobs/media-io/audio-io.c +++ b/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; diff --git a/libobs/media-io/audio-io.h b/libobs/media-io/audio-io.h index 7876a39ef..cd7d0633f 100644 --- a/libobs/media-io/audio-io.h +++ b/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); diff --git a/libobs/media-io/video-io.c b/libobs/media-io/video-io.c index 083665390..7af8b072c 100644 --- a/libobs/media-io/video-io.c +++ b/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; diff --git a/libobs/media-io/video-io.h b/libobs/media-io/video-io.h index 3c21ad638..4b8a60a46 100644 --- a/libobs/media-io/video-io.h +++ b/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); diff --git a/libobs/obs-source.c b/libobs/obs-source.c index 0d0c41964..c4d4d33b6 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -1,5 +1,5 @@ /****************************************************************************** - Copyright (C) 2013 by Hugh Bailey + Copyright (C) 2013-2014 by Hugh Bailey 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); diff --git a/libobs/obs.c b/libobs/obs.c index 8979822f5..72b397e0c 100644 --- a/libobs/obs.c +++ b/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; diff --git a/obs/forms/OBSBasicSettings.ui b/obs/forms/OBSBasicSettings.ui index 7b51ee2fb..bb48005e1 100644 --- a/obs/forms/OBSBasicSettings.ui +++ b/obs/forms/OBSBasicSettings.ui @@ -495,7 +495,7 @@ - + 0 @@ -508,6 +508,9 @@ + + true + diff --git a/obs/window-basic-main.cpp b/obs/window-basic-main.cpp index c408b2e1c..d9ba9229c 100644 --- a/obs/window-basic-main.cpp +++ b/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; diff --git a/obs/window-basic-main.hpp b/obs/window-basic-main.hpp index a7bc78a96..946319521 100644 --- a/obs/window-basic-main.hpp +++ b/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(); diff --git a/obs/window-basic-settings.cpp b/obs/window-basic-settings.cpp index a8895aec0..5b8b98126 100644 --- a/obs/window-basic-settings.cpp +++ b/obs/window-basic-settings.cpp @@ -15,6 +15,7 @@ along with this program. If not, see . ******************************************************************************/ +#include #include #include #include @@ -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 @@ -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(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);