diff --git a/libobs/CMakeLists.txt b/libobs/CMakeLists.txt index 94d729414..0edccb393 100644 --- a/libobs/CMakeLists.txt +++ b/libobs/CMakeLists.txt @@ -40,6 +40,7 @@ add_library(libobs SHARED obs-display.c obs-module.c obs-output.c + obs-encoder.c obs-scene.c obs-source.c obs-video.c diff --git a/libobs/makefile.am b/libobs/makefile.am index 074b18f26..9ab59a131 100644 --- a/libobs/makefile.am +++ b/libobs/makefile.am @@ -23,6 +23,7 @@ libobs_la_SOURCES = obs.c \ obs-output.c \ obs-scene.c \ obs-source.c \ + obs-encoder.c \ obs-video.c \ util/base.c \ util/bmem.c \ diff --git a/libobs/obs-data.h b/libobs/obs-data.h index f734d1495..bbf3599c8 100644 --- a/libobs/obs-data.h +++ b/libobs/obs-data.h @@ -30,6 +30,7 @@ #include "obs-source.h" #include "obs-output.h" #include "obs-service.h" +#include "obs-encoder.h" #define NUM_TEXTURES 2 @@ -71,10 +72,14 @@ struct obs_data { * linked lists. */ DARRAY(struct obs_display*) displays; DARRAY(struct obs_source*) sources; + DARRAY(struct obs_output*) outputs; + DARRAY(struct obs_encoder*) encoders; obs_source_t channels[MAX_CHANNELS]; pthread_mutex_t sources_mutex; pthread_mutex_t displays_mutex; + pthread_mutex_t outputs_mutex; + pthread_mutex_t encoders_mutex; }; struct obs_subsystem { @@ -83,6 +88,7 @@ struct obs_subsystem { DARRAY(struct source_info) filter_types; DARRAY(struct source_info) transition_types; DARRAY(struct output_info) output_types; + DARRAY(struct encoder_info) encoder_types; DARRAY(struct service_info) service_types; signal_handler_t signals; diff --git a/libobs/obs-defs.h b/libobs/obs-defs.h index c15b36c0b..8e9725713 100644 --- a/libobs/obs-defs.h +++ b/libobs/obs-defs.h @@ -31,3 +31,6 @@ #define SOURCE_ASYNC_VIDEO (1<<2) /* Async video (use with SOURCE_VIDEO) */ #define SOURCE_DEFAULT_EFFECT (1<<3) /* Source uses default/filter effect */ #define SOURCE_YUV (1<<4) /* Source is in YUV color space */ + +#define OUTPUT_VIDEO_ENCODER (1<<0) /* Output requires a video encoder */ +#define OUTPUT_AUDIO_ENCODER (1<<1) /* Ouptut requires an audio encoder */ diff --git a/libobs/obs-encoder.c b/libobs/obs-encoder.c new file mode 100644 index 000000000..44275c548 --- /dev/null +++ b/libobs/obs-encoder.c @@ -0,0 +1,164 @@ +/****************************************************************************** + Copyright (C) 2013 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 + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +******************************************************************************/ + +#include "obs.h" +#include "obs-data.h" + +bool load_encoder_info(void *module, const char *module_name, + const char *encoder_id, struct encoder_info *info) +{ + info->getname = load_module_subfunc(module, module_name, + encoder_id, "getname", true); + info->create = load_module_subfunc(module, module_name, + encoder_id, "create", true); + info->destroy = load_module_subfunc(module, module_name, + encoder_id, "destroy", true); + info->update = load_module_subfunc(module, module_name, + encoder_id, "update", true); + info->reset = load_module_subfunc(module, module_name, + encoder_id, "reset", true); + info->encode = load_module_subfunc(module, module_name, + encoder_id, "encode", true); + info->getheader = load_module_subfunc(module, module_name, + encoder_id, "getheader", true); + + if (!info->getname || !info->create || !info->destroy || + !info->reset || !info->encode || !info->getheader) + return false; + + info->setbitrate = load_module_subfunc(module, module_name, + encoder_id, "setbitrate", false); + info->request_keyframe = load_module_subfunc(module, module_name, + encoder_id, "request_keyframe", false); + + info->id = encoder_id; + return true; +} + +static inline struct encoder_info *get_encoder_info(const char *id) +{ + for (size_t i = 0; i < obs->encoder_types.num; i++) { + struct encoder_info *info = obs->encoder_types.array+i; + + if (strcmp(info->id, id) == 0) + return info; + } + + return NULL; +} + +const char *obs_encoder_getdisplayname(const char *id, const char *locale) +{ + struct encoder_info *ei = get_encoder_info(id); + if (!ei) + return NULL; + + return ei->getname(locale); +} + +obs_encoder_t obs_encoder_create(const char *id, const char *name, + const char *settings) +{ + struct obs_encoder *encoder; + struct encoder_info *ei = get_encoder_info(id); + + if (!ei) + return NULL; + + encoder = bmalloc(sizeof(struct obs_encoder)); + memset(encoder, 0, sizeof(struct obs_encoder)); + encoder->callbacks = *ei; + + if (pthread_mutex_init(&encoder->data_callbacks_mutex, NULL) != 0) { + bfree(encoder); + return NULL; + } + + encoder->data = ei->create(settings, encoder); + if (!encoder->data) { + pthread_mutex_destroy(&encoder->data_callbacks_mutex); + bfree(encoder); + return NULL; + } + + dstr_copy(&encoder->settings, settings); + + pthread_mutex_lock(&obs->data.encoders_mutex); + da_push_back(obs->data.encoders, &encoder); + pthread_mutex_unlock(&obs->data.encoders_mutex); + return encoder; +} + +void obs_encoder_destroy(obs_encoder_t encoder) +{ + if (encoder) { + pthread_mutex_lock(&obs->data.encoders_mutex); + da_erase_item(obs->data.encoders, &encoder); + pthread_mutex_unlock(&obs->data.encoders_mutex); + + encoder->callbacks.destroy(encoder->data); + dstr_free(&encoder->settings); + bfree(encoder); + } +} + +void obs_encoder_update(obs_encoder_t encoder, const char *settings) +{ + encoder->callbacks.update(encoder->data, settings); +} + +bool obs_encoder_reset(obs_encoder_t encoder) +{ + return encoder->callbacks.reset(encoder->data); +} + +bool obs_encoder_encode(obs_encoder_t encoder, void *frames, size_t size) +{ + /* TODO */ + //encoder->callbacks.encode(encoder->data, frames, size, packets); + return false; +} + +int obs_encoder_getheader(obs_encoder_t encoder, + struct encoder_packet **packets) +{ + return encoder->callbacks.getheader(encoder, packets); +} + +void obs_encoder_setbitrate(obs_encoder_t encoder, uint32_t bitrate, + uint32_t buffersize) +{ + if (encoder->callbacks.setbitrate) + encoder->callbacks.setbitrate(encoder->data, bitrate, + buffersize); +} + +void obs_encoder_request_keyframe(obs_encoder_t encoder) +{ + if (encoder->callbacks.request_keyframe) + encoder->callbacks.request_keyframe(encoder->data); +} + +const char *obs_encoder_get_settings(obs_encoder_t encoder) +{ + return encoder->settings.array; +} + +void obs_encoder_save_settings(obs_encoder_t encoder, const char *settings) +{ + dstr_copy(&encoder->settings, settings); +} diff --git a/libobs/obs-encoder.h b/libobs/obs-encoder.h new file mode 100644 index 000000000..d534676fc --- /dev/null +++ b/libobs/obs-encoder.h @@ -0,0 +1,147 @@ +/****************************************************************************** + Copyright (C) 2013 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 + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +******************************************************************************/ + +#pragma once + +#include "util/c99defs.h" +#include "util/dstr.h" + +/* + * =========================================== + * Outputs + * =========================================== + * + * An output takes raw audio and/or video and processes and/or outputs it + * to a destination, whether that destination be a file, network, or other. + * + * A module with outputs needs to export these functions: + * + enum_outputs + * + * Each individual output is then exported by it's name. For example, an + * output named "myoutput" would have the following exports: + * + myoutput_getname + * + myoutput_create + * + myoutput_destroy + * + myoutput_start + * + myoutput_stop + * + myoutput_encoders + * + * [and optionally] + * + myoutput_setencoder + * + myoutput_getencoder + * + myoutput_config + * + myoutput_pause + * + * =========================================== + * Primary Exports + * =========================================== + * const char *enum_outputs(size_t idx); + * idx: index of the output. + * Return value: Output identifier name. NULL when no more available. + * + * =========================================== + * Output Exports + * =========================================== + * const char *[name]_getname(const char *locale); + * Returns the full translated name of the output type (seen by the user). + * + * --------------------------------------------------------- + * void *[name]_create(const char *settings, obs_output_t output); + * Creates an output. + * + * settings: Settings of the output. + * output: pointer to main output + * Return value: Internal output pointer, or NULL if failed. + * + * --------------------------------------------------------- + * void [name]_destroy(void *data); + * Destroys the output. + * + * --------------------------------------------------------- + * void [name]_update(void *data, const char *settings) + * Updates the output's settings + * + * settings: New settings of the output + * + * --------------------------------------------------------- + * bool [name]_reset(void *data) + * Starts output + * + * Return value: true if successful + * + * --------------------------------------------------------- + * int [name]_encode(void *data, void *frames, size_t size, + * struct encoder_packet **packets) + * + * frames: frame data + * size: size of data pointed to by the frame parameter + * packets: returned packets, or NULL if none + * Return value: number of output frames + * + * --------------------------------------------------------- + * bool [name]_reset(void *data) + * Resets encoder data + * + * Return value: true if successful + * + * =========================================== + * Optional Output Exports + * =========================================== + * void [name]_setbitrate(void *data, uint32_t bitrate, uint32_t buffersize); + * Sets the bitrate of the encoder + */ + +struct obs_encoder; + +struct encoder_info { + const char *id; + + const char *(*getname)(const char *locale); + + void *(*create)(const char *settings, struct obs_encoder *encoder); + void (*destroy)(void *data); + + void (*update)(void *data, const char *settings); + + bool (*reset)(void *data); + + int (*encode)(void *data, void *frames, size_t size, + struct encoder_packet **packets); + int (*getheader)(void *data, struct encoder_packet **packets); + + /* optional */ + void (*setbitrate)(void *data, uint32_t bitrate, uint32_t buffersize); + void (*request_keyframe)(void *data); +}; + +struct obs_encoder_callback { + void (*new_packet)(void *param, struct encoder_packet *packet); + void *param; +}; + +struct obs_encoder { + char *name; + void *data; + struct encoder_info callbacks; + struct dstr settings; + + pthread_mutex_t data_callbacks_mutex; + DARRAY(struct obs_encoder_callback) data_callbacks; +}; + +extern bool load_encoder_info(void *module, const char *module_name, + const char *encoder_name, struct encoder_info *info); diff --git a/libobs/obs-module.c b/libobs/obs-module.c index 236d2b106..a9cdf6b4c 100644 --- a/libobs/obs-module.c +++ b/libobs/obs-module.c @@ -154,6 +154,8 @@ int obs_load_module(const char *path) sizeof(struct source_info), load_source_info); module_load_exports(&mod, &obs->output_types.da, "outputs", sizeof(struct output_info), load_output_info); + module_load_exports(&mod, &obs->encoder_types.da, "encoders", + sizeof(struct encoder_info), load_encoder_info); da_push_back(obs->modules, &mod); return MODULE_SUCCESS; diff --git a/libobs/obs-output.c b/libobs/obs-output.c index f6520d158..2ca3b3455 100644 --- a/libobs/obs-output.c +++ b/libobs/obs-output.c @@ -31,13 +31,15 @@ bool load_output_info(void *module, const char *module_name, output_id, "start", true); info->stop = load_module_subfunc(module, module_name, output_id, "stop", true); + info->active = load_module_subfunc(module, module_name, + output_id, "active", true); if (!info->getname || !info->create || !info->destroy || - !info->start || !info->stop) + !info->start || !info->stop || !info->active) return false; - info->config = load_module_subfunc(module, module_name, - output_id, "config", false); + info->update = load_module_subfunc(module, module_name, + output_id, "update", false); info->pause = load_module_subfunc(module, module_name, output_id, "pause", false); @@ -55,7 +57,8 @@ static inline const struct output_info *find_output(const char *id) return NULL; } -obs_output_t obs_output_create(const char *id, const char *settings) +obs_output_t obs_output_create(const char *id, const char *name, + const char *settings) { const struct output_info *info = find_output(id); struct obs_output *output; @@ -66,29 +69,39 @@ obs_output_t obs_output_create(const char *id, const char *settings) } output = bmalloc(sizeof(struct obs_output)); + output->callbacks = *info; output->data = info->create(settings, output); if (!output->data) { bfree(output); return NULL; } + output->name = bstrdup(name); dstr_init_copy(&output->settings, settings); - memcpy(&output->callbacks, info, sizeof(struct output_info)); + + pthread_mutex_lock(&obs->data.outputs_mutex); + da_push_back(obs->data.outputs, &output); + pthread_mutex_unlock(&obs->data.outputs_mutex); return output; } void obs_output_destroy(obs_output_t output) { if (output) { + pthread_mutex_lock(&obs->data.outputs_mutex); + da_erase_item(obs->data.outputs, &output); + pthread_mutex_unlock(&obs->data.outputs_mutex); + output->callbacks.destroy(output->data); dstr_free(&output->settings); + bfree(output->name); bfree(output); } } -void obs_output_start(obs_output_t output) +bool obs_output_start(obs_output_t output) { - output->callbacks.start(output->data); + return output->callbacks.start(output->data); } void obs_output_stop(obs_output_t output) @@ -96,15 +109,15 @@ void obs_output_stop(obs_output_t output) output->callbacks.stop(output->data); } -bool obs_output_canconfig(obs_output_t output) +bool obs_output_active(obs_output_t output) { - return output->callbacks.config != NULL; + return output->callbacks.active(output); } -void obs_output_config(obs_output_t output, void *parent) +void obs_output_update(obs_output_t output, const char *settings) { - if (output->callbacks.config) - output->callbacks.config(output->data, parent); + if (output->callbacks.update) + output->callbacks.update(output->data, settings); } bool obs_output_canpause(obs_output_t output) diff --git a/libobs/obs-output.h b/libobs/obs-output.h index a4054ca83..986af1a34 100644 --- a/libobs/obs-output.h +++ b/libobs/obs-output.h @@ -29,7 +29,7 @@ * to a destination, whether that destination be a file, network, or other. * * A module with outputs needs to export these functions: - * + enum_outputss + * + enum_outputs * * Each individual output is then exported by it's name. For example, an * output named "myoutput" would have the following exports: @@ -38,6 +38,7 @@ * + myoutput_destroy * + myoutput_start * + myoutput_stop + * + myoutput_encoders * * [and optionally] * + myoutput_config @@ -75,16 +76,46 @@ * settings: New settings of the output * * --------------------------------------------------------- - * void [name]_start(void *data) + * bool [name]_start(void *data) * Starts output * + * Return value: true if successful + * * --------------------------------------------------------- * void [name]_stop(void *data) * Stops output * + * --------------------------------------------------------- + * bool [name]_active(void *data) + * Returns whether currently active or not + * + * --------------------------------------------------------- + * uint32_t [name]_encoders(void *data) + * Returns 0 or a combination of the following values: + * + OUTPUT_VIDEO_ENCODER: requires a video encoder + * + OUTPUT_AUDIO_ENCODER: requires an audio encoder + * * =========================================== * Optional Output Exports * =========================================== + * bool [name]_setencoder(void *data, obs_encoder_t encoder, + * enum obs_encoder_type type) + * Sets the encoder for this output. + * + * encoder: Encoder context + * type: Type of encoder (ENCODER_VIDEO or ENCODER_AUDIO) + * + * Returns true if successful and compatible + * + * --------------------------------------------------------- + * obs_encoder_t [name]_getencoder(void *data, enum obs_encoder_type type) + * Gets the encoder for this output + * + * type: Type of encoder + * + * Returns the encoder, or NULL if none. + * + * --------------------------------------------------------- * void [name]_config(void *data, void *parent); * Called to configure the output. * @@ -105,18 +136,21 @@ struct output_info { void *(*create)(const char *settings, struct obs_output *output); void (*destroy)(void *data); - void (*start)(void *data); + bool (*start)(void *data); void (*stop)(void *data); + bool (*active)(void *data); + /* optional */ - void (*config)(void *data, void *parent); + void (*update)(void *data, const char *settings); void (*pause)(void *data); }; struct obs_output { - void *data; + char *name; + void *data; struct output_info callbacks; - struct dstr settings; + struct dstr settings; }; extern bool load_output_info(void *module, const char *module_name, diff --git a/libobs/obs-source.h b/libobs/obs-source.h index 9409a40fc..3ac074677 100644 --- a/libobs/obs-source.h +++ b/libobs/obs-source.h @@ -81,7 +81,9 @@ * Returns a combination of one of the following values: * + SOURCE_VIDEO: source has video * + SOURCE_AUDIO: source has audio - * + SOURCE_ASYNC: video is sent asynchronously via RAM + * + SOURCE_ASYNC_VIDEO: video is sent asynchronously via RAM + * + SOURCE_DEFAULT_EFFECT: source uses default effect + * + SOURCE_YUV: source is in YUV color space * * --------------------------------------------------------- * uint32_t [name]_getwidth(void *data); diff --git a/libobs/obs.c b/libobs/obs.c index 99dd36ebf..67da3170c 100644 --- a/libobs/obs.c +++ b/libobs/obs.c @@ -238,6 +238,10 @@ static bool obs_init_data(void) goto fail; if (pthread_mutex_init(&data->displays_mutex, &attr) != 0) goto fail; + if (pthread_mutex_init(&data->outputs_mutex, &attr) != 0) + goto fail; + if (pthread_mutex_init(&data->encoders_mutex, &attr) != 0) + goto fail; success = true; @@ -254,6 +258,10 @@ static void obs_free_data(void) for (i = 0; i < MAX_CHANNELS; i++) obs_set_output_source(i, NULL); + while (data->outputs.num) + obs_output_destroy(data->outputs.array[0]); + while (data->encoders.num) + obs_encoder_destroy(data->encoders.array[0]); while (data->displays.num) obs_display_destroy(data->displays.array[0]); @@ -262,6 +270,11 @@ static void obs_free_data(void) obs_source_release(data->sources.array[i]); da_free(data->sources); pthread_mutex_unlock(&obs->data.sources_mutex); + + pthread_mutex_destroy(&data->sources_mutex); + pthread_mutex_destroy(&data->displays_mutex); + pthread_mutex_destroy(&data->outputs_mutex); + pthread_mutex_destroy(&data->encoders_mutex); } static inline bool obs_init_handlers(void) @@ -487,17 +500,41 @@ void obs_set_output_source(uint32_t channel, obs_source_t source) } } -void obs_enum_sources(bool (*enum_proc)(obs_source_t, void*), void *param) +void obs_enum_outputs(bool (*enum_proc)(void*, obs_output_t), void *param) +{ + struct obs_data *data = &obs->data; + + pthread_mutex_lock(&data->outputs_mutex); + + for (size_t i = 0; i < data->outputs.num; i++) + if (!enum_proc(param, data->outputs.array[i])) + break; + + pthread_mutex_unlock(&data->outputs_mutex); +} + +void obs_enum_encoders(bool (*enum_proc)(void*, obs_encoder_t), void *param) +{ + struct obs_data *data = &obs->data; + + pthread_mutex_lock(&data->encoders_mutex); + + for (size_t i = 0; i < data->encoders.num; i++) + if (!enum_proc(param, data->encoders.array[i])) + break; + + pthread_mutex_unlock(&data->encoders_mutex); +} + +void obs_enum_sources(bool (*enum_proc)(void*, obs_source_t), void *param) { struct obs_data *data = &obs->data; - size_t i; pthread_mutex_lock(&data->sources_mutex); - for (i = 0; i < data->sources.num; i++) { - if (!enum_proc(data->sources.array[i], param)) + for (size_t i = 0; i < data->sources.num; i++) + if (!enum_proc(param, data->sources.array[i])) break; - } pthread_mutex_unlock(&data->sources_mutex); } diff --git a/libobs/obs.h b/libobs/obs.h index 78b9683df..d3c7adfb2 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -50,6 +50,11 @@ enum obs_source_type { SOURCE_SCENE }; +enum obs_encoder_type { + ENCODER_VIDEO, + ENCODER_AUDIO +}; + enum obs_video_type { OBS_VIDEO_YUV, OBS_VIDEO_RGB @@ -136,12 +141,29 @@ static inline void source_frame_destroy(struct source_frame *frame) } } +enum packet_priority { + PACKET_PRIORITY_DISPOSABLE, + PACKET_PRIORITY_LOW, + PACKET_PRIORITY_PFRAME, + PACKET_PRIORITY_IFRAME, + PACKET_PRIORITY_OTHER /* audio usually */ +}; + +struct encoder_packet { + int64_t dts; + int64_t pts; + void *data; + size_t size; + enum packet_priority priority; +}; + /* opaque types */ struct obs_display; struct obs_source; struct obs_scene; struct obs_scene_item; struct obs_output; +struct obs_encoder; struct obs_service; typedef struct obs_display *obs_display_t; @@ -149,6 +171,7 @@ typedef struct obs_source *obs_source_t; typedef struct obs_scene *obs_scene_t; typedef struct obs_scene_item *obs_sceneitem_t; typedef struct obs_output *obs_output_t; +typedef struct obs_encoder *obs_encoder_t; typedef struct obs_service *obs_service_t; /* ------------------------------------------------------------------------- */ @@ -254,7 +277,15 @@ EXPORT obs_source_t obs_get_output_source(uint32_t channel); * Callback function returns true to continue enumeration, or false to end * enumeration. */ -EXPORT void obs_enum_sources(bool (*enum_proc)(obs_source_t, void*), +EXPORT void obs_enum_sources(bool (*enum_proc)(void*, obs_source_t), + void *param); + +/** Enumerates outputs */ +EXPORT void obs_enum_outputs(bool (*enum_proc)(void*, obs_output_t), + void *param); + +/** Enumerates encoders */ +EXPORT void obs_enum_encoders(bool (*enum_proc)(void*, obs_encoder_t), void *param); /** @@ -504,26 +535,30 @@ EXPORT void obs_sceneitem_getscale(obs_sceneitem_t item, struct vec2 *scale); /* ------------------------------------------------------------------------- */ /* Outputs */ +EXPORT const char *obs_output_getdisplayname(const char *id, + const char *locale); + /** * Creates an output. * * Outputs allow outputting to file, outputting to network, outputting to * directshow, or other custom outputs. */ -EXPORT obs_output_t obs_output_create(const char *name, const char *settings); +EXPORT obs_output_t obs_output_create(const char *id, const char *name, + const char *settings); EXPORT void obs_output_destroy(obs_output_t output); /** Starts the output. */ -EXPORT void obs_output_start(obs_output_t output); +EXPORT bool obs_output_start(obs_output_t output); /** Stops the output. */ EXPORT void obs_output_stop(obs_output_t output); -/** Specifies whether the output can be configured */ -EXPORT bool obs_output_canconfig(obs_output_t output); +/** Returns whether the output is active */ +EXPORT bool obs_output_active(obs_output_t output); -/** Opens a configuration panel with the specified parent window */ -EXPORT void obs_output_config(obs_output_t output, void *parent); +/** Updates the settings for this output context */ +EXPORT void obs_output_update(obs_output_t output, const char *settings); /** Specifies whether the output can be paused */ EXPORT bool obs_output_canpause(obs_output_t output); @@ -539,13 +574,52 @@ EXPORT void obs_output_save_settings(obs_output_t output, const char *settings); +/* ------------------------------------------------------------------------- */ +/* Stream Encoders */ +EXPORT const char *obs_encoder_getdisplayname(const char *id, + const char *locale); + +EXPORT obs_encoder_t obs_encoder_create(const char *id, const char *name, + const char *settings); +EXPORT void obs_encoder_destroy(obs_encoder_t encoder); + +EXPORT void obs_encoder_update(obs_encoder_t encoder, const char *settings); + +EXPORT bool obs_encoder_reset(obs_encoder_t encoder); + +EXPORT bool obs_encoder_encode(obs_encoder_t encoder, void *frames, + size_t size); +EXPORT int obs_encoder_getheader(obs_encoder_t encoder, + struct encoder_packet **packets); + +EXPORT bool obs_encoder_start(obs_encoder_t encoder, + void (*new_packet)(void *param, struct encoder_packet *packet), + void *param); +EXPORT bool obs_encoder_stop(obs_encoder_t encoder, + void (*new_packet)(void *param, struct encoder_packet *packet), + void *param); + +EXPORT void obs_encoder_setbitrate(obs_encoder_t encoder, uint32_t bitrate, + uint32_t buffersize); + +EXPORT void obs_encoder_request_keyframe(obs_encoder_t encoder); + +EXPORT const char *obs_encoder_get_settings(obs_encoder_t encoder); + +EXPORT void obs_encoder_save_settings(obs_encoder_t encoder, + const char *settings); + + /* ------------------------------------------------------------------------- */ /* Stream Services */ +EXPORT const char *obs_service_getdisplayname(const char *id, + const char *locale); + EXPORT obs_service_t obs_service_create(const char *service, const char *settings); EXPORT void obs_service_destroy(obs_service_t service); -EXPORT void obs_service_setdata(obs_service_t service,const char *attribute, +EXPORT void obs_service_setdata(obs_service_t service, const char *attribute, const char *data); EXPORT const char *obs_service_getdata(obs_service_t service, const char *attribute); diff --git a/plugins/obs-outputs/obs-outputs.c b/plugins/obs-outputs/obs-outputs.c index 6ce9ace17..a9dd9b999 100644 --- a/plugins/obs-outputs/obs-outputs.c +++ b/plugins/obs-outputs/obs-outputs.c @@ -1,3 +1,4 @@ +#include #include "obs-outputs.h" static const char *outputs[] = {"rtmp_stream"}; diff --git a/plugins/obs-outputs/obs-outputs.h b/plugins/obs-outputs/obs-outputs.h index 4e24817cf..0601083d2 100644 --- a/plugins/obs-outputs/obs-outputs.h +++ b/plugins/obs-outputs/obs-outputs.h @@ -1,5 +1,5 @@ #pragma once -#include "util/c99defs.h" +#include EXPORT const char *enum_outputs(size_t idx); diff --git a/plugins/obs-outputs/obs-stream.c b/plugins/obs-outputs/obs-stream.c index cc0cf383d..a7405c044 100644 --- a/plugins/obs-outputs/obs-stream.c +++ b/plugins/obs-outputs/obs-stream.c @@ -1,6 +1,23 @@ +/****************************************************************************** + Copyright (C) 2013 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 + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +******************************************************************************/ + #include "obs-stream.h" -void *rtmp_stream_getname(const char *locale) +const char *rtmp_stream_getname(const char *locale) { /* TODO: locale stuff */ return "RTMP Stream"; @@ -8,21 +25,26 @@ void *rtmp_stream_getname(const char *locale) void *rtmp_stream_create(const char *settings, obs_output_t output) { - + struct rtmp_stream *stream = bmalloc(sizeof(struct rtmp_stream)); + memset(stream, 0, sizeof(struct rtmp_stream)); } -void *rtmp_stream_destroy(void *data) +void rtmp_stream_destroy(struct rtmp_stream *stream) { } -void *rtmp_stream_update(void *data, const char *settings) +void rtmp_stream_update(struct rtmp_stream *stream, const char *settings) { } -void rtmp_stream_start(void *data) +bool rtmp_stream_start(struct rtmp_stream *stream) { } -void rtmp_stream_stop(void *data) +void rtmp_stream_stop(struct rtmp_stream *stream) +{ +} + +bool rtmp_stream_active(struct rtmp_stream *stream) { } diff --git a/plugins/obs-outputs/obs-stream.h b/plugins/obs-outputs/obs-stream.h index f6f151eba..02edeb73a 100644 --- a/plugins/obs-outputs/obs-stream.h +++ b/plugins/obs-outputs/obs-stream.h @@ -1,15 +1,39 @@ +/****************************************************************************** + Copyright (C) 2013 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 + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +******************************************************************************/ + #pragma once -#include "util/c99defs.h" -#include "obs.h" +#include +#include struct rtmp_stream { - obs_output_t handler; + obs_output_t output; + obs_encoder_t video_encoder; + obs_encoder_t audio_encoder; + obs_service_t service; + + bool active; }; -EXPORT void *rtmp_stream_getname(const char *locale); +EXPORT const char *rtmp_stream_getname(const char *locale); EXPORT void *rtmp_stream_create(const char *settings, obs_output_t output); -EXPORT void *rtmp_stream_destroy(void *data); -EXPORT void *rtmp_stream_update(void *data, const char *settings); -EXPORT void rtmp_stream_start(void *data); -EXPORT void rtmp_stream_stop(void *data); +EXPORT void rtmp_stream_destroy(struct rtmp_stream *stream); +EXPORT void rtmp_stream_update(struct rtmp_stream *stream, + const char *settings); +EXPORT bool rtmp_stream_start(struct rtmp_stream *stream); +EXPORT void rtmp_stream_stop(struct rtmp_stream *stream); +EXPORT bool rtmp_stream_active(struct rtmp_stream *stream); diff --git a/plugins/obs-outputs/obs-x264.c b/plugins/obs-outputs/obs-x264.c new file mode 100644 index 000000000..d65d7e27c --- /dev/null +++ b/plugins/obs-outputs/obs-x264.c @@ -0,0 +1,58 @@ +/****************************************************************************** + Copyright (C) 2013 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 + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +******************************************************************************/ + +#include "obs-x264.h" + +const char *obs_x264_getname(const char *locale) +{ + /* TODO locale lookup */ + return "x264 (Software)"; +} + +struct obs_x264 *obs_x264_create(const char *settings, obs_encoder_t encoder) +{ + struct obs_x264 *data = bmalloc(sizeof(struct obs_x264)); +} + +void obs_x264_destroy(struct obs_x264 *data) +{ +} + +void obs_x264_update(struct obs_x264 *data, const char *settings) +{ +} + +void obs_x264_reset(struct obs_x264 *data) +{ +} + +int obs_x264_encode(struct obs_x264 *data, struct encoder_packet **packets) +{ +} + +int obs_x264_getheader(struct obs_x264 *data, struct encoder_packet **packets) +{ +} + +void obs_x264_setbitrate(struct obs_x264 *data, uint32_t bitrate, + uint32_t buffersize) +{ +} + +void obs_x264_request_keyframe(struct obs_x264 *data) +{ +} diff --git a/plugins/obs-outputs/obs-x264.h b/plugins/obs-outputs/obs-x264.h new file mode 100644 index 000000000..8190ce28b --- /dev/null +++ b/plugins/obs-outputs/obs-x264.h @@ -0,0 +1,49 @@ +/****************************************************************************** + Copyright (C) 2013 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 + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +******************************************************************************/ + +#pragma once + +#include +#include +#include + +struct obs_x264 { + obs_encoder_t encoder; + + x264_param_t params; + x264_t *context; + x264_picture_t pic_out; +}; + +EXPORT const char *obs_x264_getname(const char *locale); + +EXPORT struct obs_x264 *obs_x264_create(const char *settings, + obs_encoder_t encoder); +EXPORT void obs_x264_destroy(struct obs_x264 *data); + +EXPORT void obs_x264_update(struct obs_x264 *data, const char *settings); + +EXPORT void obs_x264_reset(struct obs_x264 *data); + +EXPORT int obs_x264_encode(struct obs_x264 *data, + struct encoder_packet **packets); +EXPORT int obs_x264_getheader(struct obs_x264 *data, + struct encoder_packet **packets); + +EXPORT void obs_x264_setbitrate(struct obs_x264 *data, uint32_t bitrate, + uint32_t buffersize); +EXPORT void obs_x264_request_keyframe(struct obs_x264 *data); diff --git a/vs/2013/libobs/libobs.vcxproj b/vs/2013/libobs/libobs.vcxproj index 481988a8e..899fcec4c 100644 --- a/vs/2013/libobs/libobs.vcxproj +++ b/vs/2013/libobs/libobs.vcxproj @@ -45,6 +45,7 @@ + @@ -91,6 +92,7 @@ + diff --git a/vs/2013/libobs/libobs.vcxproj.filters b/vs/2013/libobs/libobs.vcxproj.filters index e79d369ce..ce920f27a 100644 --- a/vs/2013/libobs/libobs.vcxproj.filters +++ b/vs/2013/libobs/libobs.vcxproj.filters @@ -198,6 +198,9 @@ callback\Header Files + + libobs\Header Files + @@ -326,5 +329,8 @@ callback\Source Files + + libobs\Source Files + \ No newline at end of file diff --git a/vs/2013/obs-outputs/obs-outputs.vcxproj b/vs/2013/obs-outputs/obs-outputs.vcxproj new file mode 100644 index 000000000..12e19fcc4 --- /dev/null +++ b/vs/2013/obs-outputs/obs-outputs.vcxproj @@ -0,0 +1,162 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {CDC3B5C9-2BEA-4509-A2A8-6477506010ED} + Win32Proj + obsoutputs + + + + DynamicLibrary + true + v120 + Unicode + + + DynamicLibrary + true + v120 + Unicode + + + DynamicLibrary + false + v120 + true + Unicode + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;OBSOUTPUTS_EXPORTS;%(PreprocessorDefinitions) + ../../../libobs + + + Windows + true + libobs.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;OBSOUTPUTS_EXPORTS;%(PreprocessorDefinitions) + ../../../libobs + + + Windows + true + libobs.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;OBSOUTPUTS_EXPORTS;%(PreprocessorDefinitions) + ../../../libobs + + + Windows + true + true + true + libobs.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;OBSOUTPUTS_EXPORTS;%(PreprocessorDefinitions) + ../../../libobs + + + Windows + true + true + true + libobs.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vs/2013/obs-outputs/obs-outputs.vcxproj.filters b/vs/2013/obs-outputs/obs-outputs.vcxproj.filters new file mode 100644 index 000000000..386f7c70a --- /dev/null +++ b/vs/2013/obs-outputs/obs-outputs.vcxproj.filters @@ -0,0 +1,39 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file