123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571 |
- Plugins
- =======
- Almost all custom functionality is added through plugin modules, which
- are typically dynamic libraries or scripts. The ability to capture
- and/or output audio/video, make a recording, output to an RTMP stream,
- encode in x264 are all examples of things that are accomplished via
- plugin modules.
- Plugins can implement sources, outputs, encoders, and services.
- Writing your first plugin? We provide `a basic template plugin <https://github.com/obsproject/obs-plugintemplate#obs-plugin-template>`_
- to get you started.
- Plugin Module Headers
- ---------------------
- These are some notable headers commonly used by plugins:
- - `libobs/obs-module.h`_ -- The primary header used for creating plugin
- modules. This file automatically includes the following files:
- - `libobs/obs.h`_ -- The main libobs header. This file automatically
- includes the following files:
- - `libobs/obs-source.h`_ -- Used for implementing sources in plugin
- modules
- - `libobs/obs-output.h`_ -- Used for implementing outputs in plugin
- modules
- - `libobs/obs-encoder.h`_ -- Used for implementing encoders in
- plugin modules
- - `libobs/obs-service.h`_ -- Used for implementing services in
- plugin modules
- - `libobs/obs-data.h`_ -- Used for managing settings for libobs
- objects
- - `libobs/obs-properties.h`_ -- Used for generating properties for
- libobs objects
- - `libobs/graphics/graphics.h`_ -- Used for graphics rendering
- Common Directory Structure and CMakeLists.txt
- ---------------------------------------------
- The common way source files are organized is to have one file for plugin
- initialization, and then specific files for each individual object
- you're implementing. For example, if you were to create a plugin called
- 'my-plugin', you'd have something like my-plugin.c where plugin
- initialization is done, my-source.c for the definition of a custom
- source, my-output.c for the definition of a custom output, etc. (This
- is not a rule of course)
- This is an example of a common directory structure for a native plugin
- module::
- my-plugin/data/locale/en-US.ini
- my-plugin/CMakeLists.txt
- my-plugin/my-plugin.c
- my-plugin/my-source.c
- my-plugin/my-output.c
- my-plugin/my-encoder.c
- my-plugin/my-service.c
- This would be an example of a common CMakeLists.txt file associated with
- these files::
- # my-plugin/CMakeLists.txt
- project(my-plugin)
- set(my-plugin_SOURCES
- my-plugin.c
- my-source.c
- my-output.c
- my-encoder.c
- my-service.c)
- add_library(my-plugin MODULE
- ${my-plugin_SOURCES})
- target_link_libraries(my-plugin
- libobs)
- install_obs_plugin_with_data(my-plugin data)
- Native Plugin Initialization
- ----------------------------
- To create a native plugin module, you will need to include the
- `libobs/obs-module.h`_ header, use :c:func:`OBS_DECLARE_MODULE()` macro,
- then create a definition of the function :c:func:`obs_module_load()`.
- In your :c:func:`obs_module_load()` function, you then register any of
- your custom sources, outputs, encoders, or services. See the
- :doc:`reference-modules` for more information.
- The following is an example of my-plugin.c, which would register one
- object of each type:
- .. code:: cpp
- /* my-plugin.c */
- #include <obs-module.h>
- /* Defines common functions (required) */
- OBS_DECLARE_MODULE()
- /* Implements common ini-based locale (optional) */
- OBS_MODULE_USE_DEFAULT_LOCALE("my-plugin", "en-US")
- extern struct obs_source_info my_source; /* Defined in my-source.c */
- extern struct obs_output_info my_output; /* Defined in my-output.c */
- extern struct obs_encoder_info my_encoder; /* Defined in my-encoder.c */
- extern struct obs_service_info my_service; /* Defined in my-service.c */
- bool obs_module_load(void)
- {
- obs_register_source(&my_source);
- obs_register_output(&my_output);
- obs_register_encoder(&my_encoder);
- obs_register_service(&my_service);
- return true;
- }
- .. _plugins_sources:
- Sources
- -------
- Sources are used to render video and/or audio on stream. Things such as
- capturing displays/games/audio, playing a video, showing an image, or
- playing audio. Sources can also be used to implement audio and video
- filters as well as transitions. The `libobs/obs-source.h`_ file is the
- dedicated header for implementing sources. See the
- :doc:`reference-sources` for more information.
- For example, to implement a source object, you need to define an
- :c:type:`obs_source_info` structure and fill it out with information and
- callbacks related to your source:
- .. code:: cpp
- /* my-source.c */
- [...]
- struct obs_source_info my_source {
- .id = "my_source",
- .type = OBS_SOURCE_TYPE_INPUT,
- .output_flags = OBS_SOURCE_VIDEO,
- .get_name = my_source_name,
- .create = my_source_create,
- .destroy = my_source_destroy,
- .update = my_source_update,
- .video_render = my_source_render,
- .get_width = my_source_width,
- .get_height = my_source_height
- };
- Then, in my-plugin.c, you would call :c:func:`obs_register_source()` in
- :c:func:`obs_module_load()` to register the source with libobs.
- .. code:: cpp
- /* my-plugin.c */
- [...]
-
- extern struct obs_source_info my_source; /* Defined in my-source.c */
- bool obs_module_load(void)
- {
- obs_register_source(&my_source);
- [...]
- return true;
- }
- Some simple examples of sources:
- - Synchronous video source: The `image source <https://github.com/obsproject/obs-studio/blob/master/plugins/image-source/image-source.c>`_
- - Asynchronous video source: The `random texture test source <https://github.com/obsproject/obs-studio/blob/master/test/test-input/test-random.c>`_
- - Audio source: The `sine wave test source <https://github.com/obsproject/obs-studio/blob/master/test/test-input/test-sinewave.c>`_
- - Video filter: The `test video filter <https://github.com/obsproject/obs-studio/blob/master/test/test-input/test-filter.c>`_
- - Audio filter: The `gain audio filter <https://github.com/obsproject/obs-studio/blob/master/plugins/obs-filters/gain-filter.c>`_
- .. _plugins_outputs:
- Outputs
- -------
- Outputs allow the ability to output the currently rendering audio/video.
- Streaming and recording are two common examples of outputs, but not the
- only types of outputs. Outputs can receive the raw data or receive
- encoded data. The `libobs/obs-output.h`_ file is the dedicated header
- for implementing outputs. See the :doc:`reference-outputs` for more
- information.
- For example, to implement an output object, you need to define an
- :c:type:`obs_output_info` structure and fill it out with information and
- callbacks related to your output:
- .. code:: cpp
- /* my-output.c */
- [...]
- struct obs_output_info my_output {
- .id = "my_output",
- .flags = OBS_OUTPUT_AV | OBS_OUTPUT_ENCODED,
- .get_name = my_output_name,
- .create = my_output_create,
- .destroy = my_output_destroy,
- .start = my_output_start,
- .stop = my_output_stop,
- .encoded_packet = my_output_data,
- .get_total_bytes = my_output_total_bytes,
- .encoded_video_codecs = "h264",
- .encoded_audio_codecs = "aac"
- };
- Then, in my-plugin.c, you would call :c:func:`obs_register_output()` in
- :c:func:`obs_module_load()` to register the output with libobs.
- .. code:: cpp
- /* my-plugin.c */
- [...]
-
- extern struct obs_output_info my_output; /* Defined in my-output.c */
- bool obs_module_load(void)
- {
- obs_register_output(&my_output);
- [...]
- return true;
- }
- Some examples of outputs:
- - Encoded video/audio outputs:
- - The `FLV output <https://github.com/obsproject/obs-studio/blob/master/plugins/obs-outputs/flv-output.c>`_
- - The `FFmpeg muxer output <https://github.com/obsproject/obs-studio/blob/master/plugins/obs-ffmpeg/obs-ffmpeg-mux.c>`_
- - The `RTMP stream output <https://github.com/obsproject/obs-studio/blob/master/plugins/obs-outputs/rtmp-stream.c>`_
- - Raw video/audio outputs:
- - The `FFmpeg output <https://github.com/obsproject/obs-studio/blob/master/plugins/obs-ffmpeg/obs-ffmpeg-output.c>`_
- .. _plugins_encoders:
- Encoders
- --------
- Encoders are OBS-specific implementations of video/audio encoders, which
- are used with outputs that use encoders. x264, NVENC, Quicksync are
- examples of encoder implementations. The `libobs/obs-encoder.h`_ file
- is the dedicated header for implementing encoders. See the
- :doc:`reference-encoders` for more information.
- For example, to implement an encoder object, you need to define an
- :c:type:`obs_encoder_info` structure and fill it out with information
- and callbacks related to your encoder:
- .. code:: cpp
- /* my-encoder.c */
- [...]
- struct obs_encoder_info my_encoder_encoder = {
- .id = "my_encoder",
- .type = OBS_ENCODER_VIDEO,
- .codec = "h264",
- .get_name = my_encoder_name,
- .create = my_encoder_create,
- .destroy = my_encoder_destroy,
- .encode = my_encoder_encode,
- .update = my_encoder_update,
- .get_extra_data = my_encoder_extra_data,
- .get_sei_data = my_encoder_sei,
- .get_video_info = my_encoder_video_info
- };
- Then, in my-plugin.c, you would call :c:func:`obs_register_encoder()`
- in :c:func:`obs_module_load()` to register the encoder with libobs.
- .. code:: cpp
- /* my-plugin.c */
- [...]
-
- extern struct obs_encoder_info my_encoder; /* Defined in my-encoder.c */
- bool obs_module_load(void)
- {
- obs_register_encoder(&my_encoder);
- [...]
- return true;
- }
- **IMPORTANT NOTE:** Encoder settings currently have a few expected
- common setting values that should have a specific naming convention:
- - **"bitrate"** - This value should be used for both video and audio
- encoders: bitrate, in kilobits.
- - **"rate_control"** - This is a setting used for video encoders.
- It's generally expected to have at least a "CBR" rate control.
- Other common rate controls are "VBR", "CQP".
- - **"keyint_sec"** - For video encoders, sets the keyframe interval
- value, in seconds, or closest possible approximation. *(Author's
- note: This should have have been "keyint", in frames.)*
- Examples of encoders:
- - Video encoders:
- - The `x264 encoder <https://github.com/obsproject/obs-studio/tree/master/plugins/obs-x264>`_
- - The `FFmpeg NVENC encoder <https://github.com/obsproject/obs-studio/blob/master/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c>`_
- - The `Quicksync encoder <https://github.com/obsproject/obs-studio/tree/master/plugins/obs-qsv11>`_
- - Audio encoders:
- - The `FFmpeg AAC/Opus encoder <https://github.com/obsproject/obs-studio/blob/master/plugins/obs-ffmpeg/obs-ffmpeg-audio-encoders.c>`_
- .. _plugins_services:
- Services
- --------
- Services are custom implementations of streaming services, which are
- used with outputs that stream. For example, you could have a custom
- implementation for streaming to Twitch, and another for YouTube to allow
- the ability to log in and use their APIs to do things such as get the
- RTMP servers or control the channel. The `libobs/obs-service.h`_ file
- is the dedicated header for implementing services. See the
- :doc:`reference-services` for more information.
- *(Author's note: the service API is incomplete as of this writing)*
- For example, to implement a service object, you need to define an
- :c:type:`obs_service_info` structure and fill it out with information
- and callbacks related to your service:
- .. code:: cpp
- /* my-service.c */
- [...]
- struct obs_service_info my_service_service = {
- .id = "my_service",
- .get_name = my_service_name,
- .create = my_service_create,
- .destroy = my_service_destroy,
- .encode = my_service_encode,
- .update = my_service_update,
- .get_url = my_service_url,
- .get_key = my_service_key
- };
- Then, in my-plugin.c, you would call :c:func:`obs_register_service()` in
- :c:func:`obs_module_load()` to register the service with libobs.
- .. code:: cpp
- /* my-plugin.c */
- [...]
-
- extern struct obs_service_info my_service; /* Defined in my-service.c */
- bool obs_module_load(void)
- {
- obs_register_service(&my_service);
- [...]
- return true;
- }
- The only two existing services objects are the "common RTMP services"
- and "custom RTMP service" objects in `plugins/rtmp-services
- <https://github.com/obsproject/obs-studio/tree/master/plugins/rtmp-services>`_
- Settings
- --------
- Settings (see `libobs/obs-data.h`_) are used to get or set settings data
- typically associated with libobs objects, and can then be saved and
- loaded via Json text. See the :doc:`reference-settings` for more
- information.
- The *obs_data_t* is the equivalent of a Json object, where it's a string
- table of sub-objects, and the *obs_data_array_t* is similarly used to
- store an array of *obs_data_t* objects, similar to Json arrays (though
- not quite identical).
- To create an *obs_data_t* or *obs_data_array_t* object, you'd call the
- :c:func:`obs_data_create()` or :c:func:`obs_data_array_create()`
- functions. *obs_data_t* and *obs_data_array_t* objects are reference
- counted, so when you are finished with the object, call
- :c:func:`obs_data_release()` or :c:func:`obs_data_array_release()` to
- release those references. Any time an *obs_data_t* or
- *obs_data_array_t* object is returned by a function, their references
- are incremented, so you must release those references each time.
- To set values for an *obs_data_t* object, you'd use one of the following
- functions:
- .. code:: cpp
- /* Set functions */
- EXPORT void obs_data_set_string(obs_data_t *data, const char *name, const char *val);
- EXPORT void obs_data_set_int(obs_data_t *data, const char *name, long long val);
- EXPORT void obs_data_set_double(obs_data_t *data, const char *name, double val);
- EXPORT void obs_data_set_bool(obs_data_t *data, const char *name, bool val);
- EXPORT void obs_data_set_obj(obs_data_t *data, const char *name, obs_data_t *obj);
- EXPORT void obs_data_set_array(obs_data_t *data, const char *name, obs_data_array_t *array);
- Similarly, to get a value from an *obs_data_t* object, you'd use one of
- the following functions:
- .. code:: cpp
- /* Get functions */
- EXPORT const char *obs_data_get_string(obs_data_t *data, const char *name);
- EXPORT long long obs_data_get_int(obs_data_t *data, const char *name);
- EXPORT double obs_data_get_double(obs_data_t *data, const char *name);
- EXPORT bool obs_data_get_bool(obs_data_t *data, const char *name);
- EXPORT obs_data_t *obs_data_get_obj(obs_data_t *data, const char *name);
- EXPORT obs_data_array_t *obs_data_get_array(obs_data_t *data, const char *name);
- Unlike typical Json data objects, the *obs_data_t* object can also set
- default values. This allows the ability to control what is returned if
- there is no value assigned to a specific string in an *obs_data_t*
- object when that data is loaded from a Json string or Json file. Each
- libobs object also has a *get_defaults* callback which allows setting
- the default settings for the object on creation.
- These functions control the default values are as follows:
- .. code:: cpp
- /* Default value functions. */
- EXPORT void obs_data_set_default_string(obs_data_t *data, const char *name, const char *val);
- EXPORT void obs_data_set_default_int(obs_data_t *data, const char *name, long long val);
- EXPORT void obs_data_set_default_double(obs_data_t *data, const char *name, double val);
- EXPORT void obs_data_set_default_bool(obs_data_t *data, const char *name, bool val);
- EXPORT void obs_data_set_default_obj(obs_data_t *data, const char *name, obs_data_t *obj);
- Properties
- ----------
- Properties (see `libobs/obs-properties.h`_) are used to automatically
- generate user interface to modify settings for a libobs object (if
- desired). Each libobs object has a *get_properties* callback which is
- used to generate properties. The properties API defines specific
- properties that are linked to the object's settings, and the front-end
- uses those properties to generate widgets in order to allow the user to
- modify the settings. For example, if you had a boolean setting, you
- would use :c:func:`obs_properties_add_bool()` to allow the user to be
- able to change that setting. See the :doc:`reference-properties` for
- more information.
- An example of this:
- .. code:: cpp
- static obs_properties_t *my_source_properties(void *data)
- {
- obs_properties_t *ppts = obs_properties_create();
- obs_properties_add_bool(ppts, "my_bool",
- obs_module_text("MyBool"));
- UNUSED_PARAMETER(data);
- return ppts;
- }
- [...]
- struct obs_source_info my_source {
- .get_properties = my_source_properties,
- [...]
- };
- The *data* parameter is the object's data if the object is present.
- Typically this is unused and probably shouldn't be used if possible. It
- can be null if the properties are retrieved without an object associated
- with it.
- Properties can also be modified depending on what settings are shown.
- For example, you can mark certain properties as disabled or invisible
- depending on what a particular setting is set to using the
- :c:func:`obs_property_set_modified_callback()` function.
- For example, if you wanted boolean property A to hide text property B:
- .. code:: cpp
- static bool setting_a_modified(obs_properties_t *ppts,
- obs_property_t *p, obs_data_t *settings)
- {
- bool enabled = obs_data_get_bool(settings, "setting_a");
- p = obs_properties_get(ppts, "setting_b");
- obs_property_set_enabled(p, enabled);
- /* return true to update property widgets, false
- otherwise */
- return true;
- }
- [...]
- static obs_properties_t *my_source_properties(void *data)
- {
- obs_properties_t *ppts = obs_properties_create();
- obs_property_t *p;
- p = obs_properties_add_bool(ppts, "setting_a",
- obs_module_text("SettingA"));
- obs_property_set_modified_callback(p, setting_a_modified);
- obs_properties_add_text(ppts, "setting_b",
- obs_module_text("SettingB"),
- OBS_TEXT_DEFAULT);
- return ppts;
- }
- Localization
- ------------
- Typically, most plugins bundled with OBS Studio will use a simple
- ini-file localization method, where each file is a different language.
- When using this method, the :c:func:`OBS_MODULE_USE_DEFAULT_LOCALE()`
- macro is used which will automatically load/destroy the locale data with
- no extra effort on part of the plugin. Then the
- :c:func:`obs_module_text()` function (which is automatically declared as
- an extern by `libobs/obs-module.h`_) is used when text lookup is needed.
- There are two exports the module used to load/destroy locale: the
- :c:func:`obs_module_set_locale()` export, and the
- :c:func:`obs_module_free_locale()` export. The
- :c:func:`obs_module_set_locale()` export is called by libobs to set the
- current language, and then the :c:func:`obs_module_free_locale()` export
- is called by libobs on destruction of the module. If you wish to
- implement a custom locale implementation for your plugin, you'd want to
- define these exports along with the :c:func:`obs_module_text()` extern
- yourself instead of relying on the
- :c:func:`OBS_MODULE_USE_DEFAULT_LOCALE()` macro.
- .. ---------------------------------------------------------------------------
- .. _libobs/obs-module.h: https://github.com/obsproject/obs-studio/blob/master/libobs/obs-module.h
- .. _libobs/obs.h: https://github.com/obsproject/obs-studio/blob/master/libobs/obs.h
- .. _libobs/obs-source.h: https://github.com/obsproject/obs-studio/blob/master/libobs/obs-source.h
- .. _libobs/obs-output.h: https://github.com/obsproject/obs-studio/blob/master/libobs/obs-output.h
- .. _libobs/obs-encoder.h: https://github.com/obsproject/obs-studio/blob/master/libobs/obs-encoder.h
- .. _libobs/obs-service.h: https://github.com/obsproject/obs-studio/blob/master/libobs/obs-service.h
- .. _libobs/obs-data.h: https://github.com/obsproject/obs-studio/blob/master/libobs/obs-data.h
- .. _libobs/obs-properties.h: https://github.com/obsproject/obs-studio/blob/master/libobs/obs-properties.h
- .. _libobs/graphics/graphics.h: https://github.com/obsproject/obs-studio/blob/master/libobs/graphics/graphics.h
|