diff --git a/docs/sphinx/reference-sources.rst b/docs/sphinx/reference-sources.rst index 45f2f5855..26bfed7f0 100644 --- a/docs/sphinx/reference-sources.rst +++ b/docs/sphinx/reference-sources.rst @@ -48,13 +48,13 @@ Source Definition Structure (obs_source_info) A bitwise OR combination of one or more of the following values: - **OBS_SOURCE_VIDEO** - Source has video - + Unless SOURCE_ASYNC_VIDEO is specified, the source must include the :c:member:`obs_source_info.video_render` callback in the source definition structure. - **OBS_SOURCE_AUDIO** - Source has audio - + Use the :c:func:`obs_source_output_audio()` function to pass raw audio data, which will be automatically converted and uploaded. If used with OBS_SOURCE_ASYNC_VIDEO, audio will automatically be @@ -69,7 +69,7 @@ Source Definition Structure (obs_source_info) Use the :c:func:`obs_source_output_video()` function to pass raw video data, which will be automatically drawn at a timing relative to the provided timestamp. - + If audio is also present on the source, the audio will automatically be synced to the video based upon their mutual timestamps. @@ -108,7 +108,7 @@ Source Definition Structure (obs_source_info) When used, specifies that the source composites one or more child sources. Scenes and transitions are examples of sources that contain and render child sources. - + Sources that render sub-sources must implement the audio_render callback in order to perform custom audio mixing of child sources. @@ -661,7 +661,7 @@ General Source Functions .. function:: obs_source_t *obs_source_create(const char *id, const char *name, obs_data_t *settings, obs_data_t *hotkey_data) Creates a source of the specified type with the specified settings. - + The "source" context is used for anything related to presenting or modifying video/audio. Use obs_source_release to release it. @@ -1032,6 +1032,13 @@ General Source Functions --------------------- +.. function:: obs_data_array_t *obs_source_backup_filters(obs_source_t *source) + void obs_source_restore_filters(obs_source_t *source, obs_data_array_t *array) + + Backs up and restores the current filter list and order. + +--------------------- + .. function:: bool obs_source_enabled(const obs_source_t *source) void obs_source_set_enabled(obs_source_t *source, bool enabled) @@ -1132,7 +1139,7 @@ Functions used by sources Helper function to set the color matrix information when drawing the source. - + :param color_matrix: The color matrix. Assigns to the 'color_matrix' effect variable. :param color_range_min: The minimum color range. Assigns to the @@ -1147,7 +1154,7 @@ Functions used by sources .. function:: void obs_source_draw(gs_texture_t *image, int x, int y, uint32_t cx, uint32_t cy, bool flip) Helper function to draw sprites for a source (synchronous video). - + :param image: The sprite texture to draw. Assigns to the 'image' variable of the current effect. :param x: X position of the sprite. @@ -1168,22 +1175,22 @@ Functions used by sources enum video_format { VIDEO_FORMAT_NONE, - + /* planar 420 format */ VIDEO_FORMAT_I420, /* three-plane */ VIDEO_FORMAT_NV12, /* two-plane, luma and packed chroma */ - + /* packed 422 formats */ VIDEO_FORMAT_YVYU, VIDEO_FORMAT_YUY2, /* YUYV */ VIDEO_FORMAT_UYVY, - + /* packed uncompressed formats */ VIDEO_FORMAT_RGBA, VIDEO_FORMAT_BGRA, VIDEO_FORMAT_BGRX, VIDEO_FORMAT_Y800, /* grayscale */ - + /* planar 4:4:4 */ VIDEO_FORMAT_I444, }; @@ -1194,7 +1201,7 @@ Functions used by sources uint32_t width; uint32_t height; uint64_t timestamp; - + enum video_format format; float color_matrix[16]; bool full_range; @@ -1223,7 +1230,7 @@ Functions used by sources .. function:: void obs_source_show_preloaded_video(obs_source_t *source) Shows any preloaded video frame. - + --------------------- .. function:: void obs_source_output_audio(obs_source_t *source, const struct obs_source_audio *audio) @@ -1243,7 +1250,7 @@ Functions used by sources Adds an active child source. Must be called by parent sources on child sources when the child is added and active. This ensures that the source is properly activated if the parent is active. - + :return: *true* if source can be added, *false* if it causes recursion --------------------- @@ -1264,7 +1271,7 @@ Filters If the source is a filter, returns the parent source of the filter. The parent source is the source being filtered. - + Only guaranteed to be valid inside of the video_render, filter_audio, filter_video, and filter_remove callbacks. @@ -1274,7 +1281,7 @@ Filters If the source is a filter, returns the target source of the filter. The target source is the next source in the filter chain. - + Only guaranteed to be valid inside of the video_render, filter_audio, filter_video, and filter_remove callbacks. @@ -1315,10 +1322,10 @@ Functions used by filters Default RGB filter handler for generic effect filters. Processes the filter chain and renders them to texture if needed, then the filter is drawn with. - + After calling this, set your parameters for the effect, then call obs_source_process_filter_end to draw the filter. - + :return: *true* if filtering should continue, *false* if the filter is bypassed for whatever reason @@ -1327,7 +1334,7 @@ Functions used by filters .. function:: void obs_source_process_filter_end(obs_source_t *filter, gs_effect_t *effect, uint32_t width, uint32_t height) Draws the filter using the effect's "Draw" technique. - + Before calling this function, first call obs_source_process_filter_begin and then set the effect parameters, and then call this function to finalize the filter. @@ -1337,7 +1344,7 @@ Functions used by filters .. function:: void obs_source_process_filter_end_srgb(obs_source_t *filter, gs_effect_t *effect, uint32_t width, uint32_t height) Draws the filter using the effect's "Draw" technique, and use automatic SRGB conversion. - + Before calling this function, first call obs_source_process_filter_begin and then set the effect parameters, and then call this function to finalize the filter. @@ -1347,7 +1354,7 @@ Functions used by filters .. function:: void obs_source_process_filter_tech_end(obs_source_t *filter, gs_effect_t *effect, uint32_t width, uint32_t height, const char *tech_name) Draws the filter with a specific technique in the effect. - + Before calling this function, first call obs_source_process_filter_begin and then set the effect parameters, and then call this function to finalize the filter. @@ -1357,7 +1364,7 @@ Functions used by filters .. function:: void obs_source_process_filter_tech_end_srgb(obs_source_t *filter, gs_effect_t *effect, uint32_t width, uint32_t height, const char *tech_name) Draws the filter with a specific technique in the effect, and use automatic SRGB conversion. - + Before calling this function, first call obs_source_process_filter_begin and then set the effect parameters, and then call this function to finalize the filter. @@ -1452,7 +1459,7 @@ Functions used by transitions bool obs_transition_fixed(obs_source_t *transition) Sets/gets whether the transition uses a fixed duration. Useful for - certain types of transitions such as stingers. If this is set, the + certain types of transitions such as stingers. If this is set, the *duration_ms* parameter of :c:func:`obs_transition_start()` has no effect. @@ -1508,7 +1515,7 @@ Functions used by transitions source, then call obs_transition_swap_end when complete. This allows the ability to seamlessly swap two different transitions without it affecting the output. - + For example, if a transition is assigned to output channel 0, you'd call obs_transition_swap_begin, then you'd call obs_set_output_source with the new transition, then call diff --git a/libobs/obs-source.c b/libobs/obs-source.c index 241dcdfe2..af0f940b2 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -5244,3 +5244,98 @@ void obs_source_media_ended(obs_source_t *source) obs_source_dosignal(source, NULL, "media_ended"); } + +obs_data_array_t *obs_source_backup_filters(obs_source_t *source) +{ + if (!obs_source_valid(source, "obs_source_backup_filters")) + return NULL; + + obs_data_array_t *array = obs_data_array_create(); + + pthread_mutex_lock(&source->filter_mutex); + for (size_t i = 0; i < source->filters.num; i++) { + struct obs_source *filter = source->filters.array[i]; + obs_data_t *data = obs_save_source(filter); + obs_data_array_push_back(array, data); + obs_data_release(data); + } + pthread_mutex_unlock(&source->filter_mutex); + + return array; +} + +void obs_source_restore_filters(obs_source_t *source, obs_data_array_t *array) +{ + if (!obs_source_valid(source, "obs_source_restore_filters")) + return; + if (!obs_ptr_valid(array, "obs_source_restore_filters")) + return; + + DARRAY(obs_source_t *) cur_filters; + DARRAY(obs_source_t *) new_filters; + obs_source_t *prev = NULL; + + da_init(cur_filters); + da_init(new_filters); + + pthread_mutex_lock(&source->filter_mutex); + + /* clear filter list */ + da_reserve(cur_filters, source->filters.num); + da_reserve(new_filters, source->filters.num); + for (size_t i = 0; i < source->filters.num; i++) { + obs_source_t *filter = source->filters.array[i]; + da_push_back(cur_filters, &filter); + filter->filter_parent = NULL; + filter->filter_target = NULL; + } + + da_free(source->filters); + pthread_mutex_unlock(&source->filter_mutex); + + /* add backed up filters */ + size_t count = obs_data_array_count(array); + for (size_t i = 0; i < count; i++) { + obs_data_t *data = obs_data_array_item(array, i); + const char *name = obs_data_get_string(data, "name"); + obs_source_t *filter = NULL; + + /* if backed up filter already exists, don't create */ + for (size_t j = 0; j < cur_filters.num; j++) { + obs_source_t *cur = cur_filters.array[j]; + const char *cur_name = cur->context.name; + if (cur_name && strcmp(cur_name, name) == 0) { + filter = cur; + obs_source_addref(cur); + break; + } + } + + if (!filter) + filter = obs_load_source(data); + + /* add filter */ + if (prev) + prev->filter_target = filter; + prev = filter; + filter->filter_parent = source; + da_push_back(new_filters, &filter); + + obs_data_release(data); + } + + if (prev) + prev->filter_target = source; + + pthread_mutex_lock(&source->filter_mutex); + da_move(source->filters, new_filters); + pthread_mutex_unlock(&source->filter_mutex); + + /* release filters */ + for (size_t i = 0; i < cur_filters.num; i++) { + obs_source_t *filter = cur_filters.array[i]; + obs_source_release(filter); + } + + da_free(cur_filters); +} diff --git a/libobs/obs.h b/libobs/obs.h index e3c9567a2..320321aec 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -1204,6 +1204,10 @@ obs_source_get_monitoring_type(const obs_source_t *source); * automatically. Returns an incremented reference. */ EXPORT obs_data_t *obs_source_get_private_settings(obs_source_t *item); +EXPORT obs_data_array_t *obs_source_backup_filters(obs_source_t *source); +EXPORT void obs_source_restore_filters(obs_source_t *source, + obs_data_array_t *array); + /* ------------------------------------------------------------------------- */ /* Functions used by sources */