diff --git a/libobs/CMakeLists.txt b/libobs/CMakeLists.txt index fa4d46fb3..94d729414 100644 --- a/libobs/CMakeLists.txt +++ b/libobs/CMakeLists.txt @@ -56,7 +56,6 @@ add_library(libobs SHARED media-io/audio-io.c media-io/format-conversion.c media-io/audio-resampler-ffmpeg.c - media-io/media-io.c media-io/video-io.c graphics/axisang.c graphics/bounds.c diff --git a/libobs/makefile.am b/libobs/makefile.am index aebdc75d2..074b18f26 100644 --- a/libobs/makefile.am +++ b/libobs/makefile.am @@ -37,7 +37,6 @@ libobs_la_SOURCES = obs.c \ media-io/audio-io.c \ media-io/format-conversion.c \ media-io/audio-resampler-ffmpeg.c \ - media-io/media-io.c \ media-io/video-io.c \ graphics/axisang.c \ graphics/bounds.c \ diff --git a/libobs/media-io/audio-io.c b/libobs/media-io/audio-io.c index 085ccd23d..c95abbef6 100644 --- a/libobs/media-io/audio-io.c +++ b/libobs/media-io/audio-io.c @@ -22,7 +22,11 @@ #include "audio-io.h" -/* TODO: Incomplete */ +struct audio_input { + struct audio_info format; + void (*callback)(void *param, const struct audio_data *data); + void *param; +}; struct audio_line { char *name; @@ -52,11 +56,9 @@ static inline void audio_line_destroy_data(struct audio_line *line) } struct audio_output { - struct audio_info info; + struct audio_output_info info; size_t block_size; size_t channels; - media_t media; - media_output_t output; pthread_t thread; event_t stop_event; @@ -69,6 +71,9 @@ struct audio_output { pthread_mutex_t line_mutex; struct audio_line *first_line; + + pthread_mutex_t input_mutex; + DARRAY(struct audio_input) inputs; }; static inline void audio_output_removeline(struct audio_output *audio, @@ -76,18 +81,25 @@ static inline void audio_output_removeline(struct audio_output *audio, { pthread_mutex_lock(&audio->line_mutex); *line->prev_next = line->next; + if (line->next) + line->next->prev_next = line->prev_next; pthread_mutex_unlock(&audio->line_mutex); audio_line_destroy_data(line); } -static inline size_t convert_to_sample_offset(audio_t audio, uint64_t offset) +static inline size_t time_to_frames(audio_t audio, uint64_t offset) { double audio_offset_d = (double)offset; audio_offset_d /= 1000000000.0; audio_offset_d *= (double)audio->info.samples_per_sec; - return (size_t)audio_offset_d * audio->block_size; + return (size_t)audio_offset_d; +} + +static inline size_t time_to_bytes(audio_t audio, uint64_t offset) +{ + return time_to_frames(audio, offset) * audio->block_size; } /* ------------------------------------------------------------------------- */ @@ -120,7 +132,7 @@ static inline void mix_audio_line(struct audio_output *audio, return; } - size_t time_offset = convert_to_sample_offset(audio, + size_t time_offset = time_to_bytes(audio, line->base_timestamp - timestamp); if (time_offset > size) return; @@ -133,15 +145,34 @@ static inline void mix_audio_line(struct audio_output *audio, pop_size); } -static void mix_audio_lines(struct audio_output *audio, uint64_t audio_time, +static inline void do_audio_output(struct audio_output *audio, + uint64_t timestamp, size_t frames) +{ + struct audio_data data; + data.data = audio->mix_buffer.array; + data.frames = frames; + data.timestamp = timestamp; + data.volume = 1.0f; + + /* TODO: conversion */ + pthread_mutex_lock(&audio->input_mutex); + for (size_t i = 0; i < audio->inputs.num; i++) { + struct audio_input *input = audio->inputs.array+i; + input->callback(input->param, &data); + } + pthread_mutex_unlock(&audio->input_mutex); +} + +static void mix_and_output(struct audio_output *audio, uint64_t audio_time, uint64_t prev_time) { struct audio_line *line = audio->first_line; uint64_t time_offset = audio_time - prev_time; - size_t byte_offset = convert_to_sample_offset(audio, time_offset); + size_t frames = time_to_frames(audio, time_offset); + size_t bytes = frames * audio->block_size; - da_resize(audio->mix_buffer, byte_offset); - memset(audio->mix_buffer.array, 0, byte_offset); + da_resize(audio->mix_buffer, bytes); + memset(audio->mix_buffer.array, 0, bytes); while (line) { struct audio_line *next = line->next; @@ -152,14 +183,12 @@ static void mix_audio_lines(struct audio_output *audio, uint64_t audio_time, line->base_timestamp = prev_time; } - mix_audio_line(audio, line, byte_offset, prev_time); + mix_audio_line(audio, line, bytes, prev_time); line->base_timestamp = audio_time; line = next; } - /* TODO - not good enough */ - /*if (audio->output) - media_output_data(audio->output, audio->mix_buffer.array);*/ + do_audio_output(audio, prev_time, frames); } /* sample audio 40 times a second */ @@ -178,7 +207,7 @@ static void *audio_thread(void *param) pthread_mutex_lock(&audio->line_mutex); audio_time = os_gettime_ns() - buffer_time; - mix_audio_lines(audio, audio_time, prev_time); + mix_and_output(audio, audio_time, prev_time); prev_time = audio_time; pthread_mutex_unlock(&audio->line_mutex); @@ -189,28 +218,66 @@ static void *audio_thread(void *param) /* ------------------------------------------------------------------------- */ -static inline bool valid_audio_params(struct audio_info *info) +static size_t audio_get_input_idx(audio_t video, + void (*callback)(void *param, const struct audio_data *data), + void *param) +{ + for (size_t i = 0; i < video->inputs.num; i++) { + struct audio_input *input = video->inputs.array+i; + if (input->callback == callback && input->param == param) + return i; + } + + return DARRAY_INVALID; +} + +void audio_output_connect(audio_t audio, struct audio_info *format, + void (*callback)(void *param, const struct audio_data *data), + void *param) +{ + pthread_mutex_lock(&audio->input_mutex); + + if (audio_get_input_idx(audio, callback, param) != DARRAY_INVALID) { + struct audio_input input; + input.callback = callback; + input.param = param; + + /* TODO: conversion */ + if (format) { + input.format = *format; + } else { + input.format.format = audio->info.format; + input.format.speakers = audio->info.speakers; + input.format.samples_per_sec = + audio->info.samples_per_sec; + } + + da_push_back(audio->inputs, &input); + } + + pthread_mutex_unlock(&audio->input_mutex); +} + +void audio_output_disconnect(audio_t audio, + void (*callback)(void *param, const struct audio_data *data), + void *param) +{ + pthread_mutex_lock(&audio->input_mutex); + + size_t idx = audio_get_input_idx(audio, callback, param); + if (idx != DARRAY_INVALID) + da_erase(audio->inputs, idx); + + pthread_mutex_unlock(&audio->input_mutex); +} + +static inline bool valid_audio_params(struct audio_output_info *info) { return info->format && info->name && info->samples_per_sec > 0 && info->speakers > 0; } -static bool ao_add_to_media(audio_t audio) -{ - struct media_output_info oi; - oi.obj = audio; - oi.connect = NULL; - oi.format = NULL; /* TODO */ - - audio->output = media_output_create(&oi); - if (!audio->output) - return false; - - media_add_output(audio->media, audio->output); - return true; -} - -int audio_output_open(audio_t *audio, media_t media, struct audio_info *info) +int audio_output_open(audio_t *audio, struct audio_output_info *info) { struct audio_output *out; pthread_mutexattr_t attr; @@ -221,9 +288,8 @@ int audio_output_open(audio_t *audio, media_t media, struct audio_info *info) out = bmalloc(sizeof(struct audio_output)); memset(out, 0, sizeof(struct audio_output)); - memcpy(&out->info, info, sizeof(struct audio_info)); + memcpy(&out->info, info, sizeof(struct audio_output_info)); pthread_mutex_init_value(&out->line_mutex); - out->media = media; out->channels = get_audio_channels(info->speakers); out->block_size = out->channels * get_audio_bytes_per_channel(info->format); @@ -234,9 +300,9 @@ int audio_output_open(audio_t *audio, media_t media, struct audio_info *info) goto fail; if (pthread_mutex_init(&out->line_mutex, &attr) != 0) goto fail; - if (event_init(&out->stop_event, EVENT_TYPE_MANUAL) != 0) + if (pthread_mutex_init(&out->input_mutex, NULL) != 0) goto fail; - if (!ao_add_to_media(out)) + if (event_init(&out->stop_event, EVENT_TYPE_MANUAL) != 0) goto fail; if (pthread_create(&out->thread, NULL, audio_thread, out) != 0) goto fail; @@ -250,6 +316,33 @@ fail: return AUDIO_OUTPUT_FAIL; } +void audio_output_close(audio_t audio) +{ + void *thread_ret; + struct audio_line *line; + + if (!audio) + return; + + if (audio->initialized) { + event_signal(&audio->stop_event); + pthread_join(audio->thread, &thread_ret); + } + + line = audio->first_line; + while (line) { + struct audio_line *next = line->next; + audio_line_destroy_data(line); + line = next; + } + + da_free(audio->mix_buffer); + da_free(audio->pending_bytes); + event_destroy(&audio->stop_event); + pthread_mutex_destroy(&audio->line_mutex); + bfree(audio); +} + audio_line_t audio_output_createline(audio_t audio, const char *name) { struct audio_line *line = bmalloc(sizeof(struct audio_line)); @@ -280,40 +373,11 @@ audio_line_t audio_output_createline(audio_t audio, const char *name) return line; } -const struct audio_info *audio_output_getinfo(audio_t audio) +const struct audio_output_info *audio_output_getinfo(audio_t audio) { return &audio->info; } -void audio_output_close(audio_t audio) -{ - void *thread_ret; - struct audio_line *line; - - if (!audio) - return; - - if (audio->initialized) { - event_signal(&audio->stop_event); - pthread_join(audio->thread, &thread_ret); - } - - line = audio->first_line; - while (line) { - struct audio_line *next = line->next; - audio_line_destroy_data(line); - line = next; - } - - da_free(audio->mix_buffer); - da_free(audio->pending_bytes); - media_remove_output(audio->media, audio->output); - media_output_destroy(audio->output); - event_destroy(&audio->stop_event); - pthread_mutex_destroy(&audio->line_mutex); - bfree(audio); -} - void audio_line_destroy(struct audio_line *line) { if (line) { @@ -436,7 +500,7 @@ static inline void audio_line_place_data(struct audio_line *line, const struct audio_data *data) { uint64_t time_offset = data->timestamp - line->base_timestamp; - size_t pos = convert_to_sample_offset(line->audio, time_offset); + size_t pos = time_to_bytes(line->audio, time_offset); audio_line_place_data_pos(line, data, pos); } diff --git a/libobs/media-io/audio-io.h b/libobs/media-io/audio-io.h index e743fcda0..5715f1c27 100644 --- a/libobs/media-io/audio-io.h +++ b/libobs/media-io/audio-io.h @@ -18,7 +18,6 @@ #pragma once #include "../util/c99defs.h" -#include "media-io.h" #ifdef __cplusplus extern "C" { @@ -63,16 +62,21 @@ struct audio_data { float volume; }; -struct audio_info { +struct audio_output_info { const char *name; uint32_t samples_per_sec; enum audio_format format; enum speaker_layout speakers; - uint64_t buffer_ms; }; +struct audio_info { + uint32_t samples_per_sec; + enum audio_format format; + enum speaker_layout speakers; +}; + static inline uint32_t get_audio_channels(enum speaker_layout speakers) { switch (speakers) { @@ -117,13 +121,20 @@ static inline size_t get_audio_size(enum audio_format type, #define AUDIO_OUTPUT_INVALIDPARAM -1 #define AUDIO_OUTPUT_FAIL -2 -EXPORT int audio_output_open(audio_t *audio, media_t media, - struct audio_info *info); -EXPORT audio_line_t audio_output_createline(audio_t audio, const char *name); -EXPORT size_t audio_output_blocksize(audio_t audio); -EXPORT const struct audio_info *audio_output_getinfo(audio_t audio); +EXPORT int audio_output_open(audio_t *audio, struct audio_output_info *info); EXPORT void audio_output_close(audio_t audio); +EXPORT void audio_output_connect(audio_t video, struct audio_info *format, + void (*callback)(void *param, const struct audio_data *data), + void *param); +EXPORT void audio_output_disconnect(audio_t video, + void (*callback)(void *param, const struct audio_data *data), + void *param); + +EXPORT size_t audio_output_blocksize(audio_t audio); +EXPORT const struct audio_output_info *audio_output_getinfo(audio_t audio); + +EXPORT audio_line_t audio_output_createline(audio_t audio, const char *name); EXPORT void audio_line_destroy(audio_line_t line); EXPORT void audio_line_output(audio_line_t line, const struct audio_data *data); diff --git a/libobs/media-io/audio-mixer.h b/libobs/media-io/audio-mixer.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/libobs/media-io/media-io.c b/libobs/media-io/media-io.c deleted file mode 100644 index eab630e3f..000000000 --- a/libobs/media-io/media-io.c +++ /dev/null @@ -1,159 +0,0 @@ -/****************************************************************************** - 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 "../util/threading.h" -#include "../util/darray.h" -#include "../util/bmem.h" - -#include "media-io.h" - -/* TODO: Incomplete */ - -struct media_input { - struct media_input_info info; - struct media_output *connection; -}; - -struct media_output { - struct media_output_info info; - DARRAY(media_input_t) connections; - pthread_mutex_t mutex; -}; - -struct media_data { - DARRAY(media_output_t) outputs; -}; - -/* ------------------------------------------------------------------------- */ - -media_input_t media_input_create(struct media_input_info *info) -{ - struct media_input *input; - - if (!info || !info->format || !info->on_input) - return NULL; - - input = bmalloc(sizeof(struct media_input)); - input->connection = NULL; - memcpy(&input->info, info, sizeof(struct media_input_info)); - - return input; -} - -void media_input_destroy(media_input_t input) -{ - if (input) - bfree(input); -} - -/* ------------------------------------------------------------------------- */ - -media_output_t media_output_create(struct media_output_info *info) -{ - struct media_output *output; - - /* TODO: handle format */ - if (!info) // || !info->format) - return NULL; - - output = bmalloc(sizeof(struct media_output)); - da_init(output->connections); - memcpy(&output->info, info, sizeof(struct media_output_info)); - - if (pthread_mutex_init(&output->mutex, NULL) != 0) { - bfree(output); - return NULL; - } - - return output; -} - -void media_output_data(media_output_t output, const void *data) -{ - size_t i; - - pthread_mutex_lock(&output->mutex); - - for (i = 0; i < output->connections.num; i++) { - media_input_t input = output->connections.array[i]; - input->info.on_input(input->info.obj, data); - } - - pthread_mutex_unlock(&output->mutex); -} - -void media_output_destroy(media_output_t output) -{ - if (output) { - da_free(output->connections); - pthread_mutex_destroy(&output->mutex); - bfree(output); - } -} - -/* ------------------------------------------------------------------------- */ - -media_t media_open(void) -{ - struct media_data *media = bmalloc(sizeof(struct media_data)); - da_init(media->outputs); - - return media; -} - -bool media_add_input(media_t media, media_input_t input) -{ - media_output_t *outputs = media->outputs.array; - size_t i; - - for (i = 0; i < media->outputs.num; i++) { - media_output_t output = outputs[i]; - - if (strcmp(output->info.format, input->info.format) == 0) { - da_push_back(output->connections, input); - return true; - } - } - - return false; -} - -void media_add_output(media_t media, media_output_t output) -{ - da_push_back(media->outputs, output); -} - -void media_remove_input(media_t media, media_input_t input) -{ - if (!input->connection) - return; - - da_erase_item(input->connection->connections, input); -} - -void media_remove_output(media_t media, media_output_t output) -{ - da_erase_item(media->outputs, output); -} - -void media_close(media_t media) -{ - if (media) { - da_free(media->outputs); - bfree(media); - } -} diff --git a/libobs/media-io/media-io.h b/libobs/media-io/media-io.h deleted file mode 100644 index 608d88637..000000000 --- a/libobs/media-io/media-io.h +++ /dev/null @@ -1,74 +0,0 @@ -/****************************************************************************** - 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 - -/* - * Media input/output components used for connecting media outputs/inputs - * together. An input requests a connection to an output and the output - * sends frames to it through the callbacks in media_data_in structure. - * - * The id member should indicate the format/parameters used in text form. - */ - -/* opaque data types */ -struct media_input; -struct media_output; -struct media_data; -typedef struct media_input *media_input_t; -typedef struct media_output *media_output_t; -typedef struct media_data *media_t; - -#include "../util/c99defs.h" -#include "video-io.h" -#include "audio-io.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct media_input_info { - const char *format; - - void *obj; - void (*on_input)(void *obj, const void *data); -}; - -struct media_output_info { - const char *format; - - void *obj; - bool (*connect)(void *obj, media_input_t input); -}; - -EXPORT media_input_t media_input_create(struct media_input_info *info); -EXPORT void media_input_destroy(media_input_t input); - -EXPORT media_output_t media_output_create(struct media_output_info *info); -EXPORT void media_output_data(media_output_t out, const void *data); -EXPORT void media_output_destroy(media_output_t output); - -EXPORT media_t media_open(void); -EXPORT bool media_add_input(media_t media, media_input_t input); -EXPORT void media_add_output(media_t media, media_output_t output); -EXPORT void media_remove_input(media_t media, media_input_t input); -EXPORT void media_remove_output(media_t media, media_output_t output); -EXPORT void media_close(media_t media); - -#ifdef __cplusplus -} -#endif diff --git a/libobs/media-io/video-io.c b/libobs/media-io/video-io.c index be8701fe4..8e7abaa7d 100644 --- a/libobs/media-io/video-io.c +++ b/libobs/media-io/video-io.c @@ -19,25 +19,33 @@ #include "../util/bmem.h" #include "../util/platform.h" #include "../util/threading.h" +#include "../util/darray.h" #include "video-io.h" +struct video_input { + struct video_info format; + void (*callback)(void *param, struct video_frame *frame); + void *param; +}; + struct video_output { - struct video_info info; - media_t media; - media_output_t output; + struct video_output_info info; - pthread_t thread; - pthread_mutex_t data_mutex; - event_t stop_event; + pthread_t thread; + pthread_mutex_t data_mutex; + event_t stop_event; - struct video_frame *cur_frame; - struct video_frame *next_frame; - event_t update_event; - uint64_t frame_time; - volatile uint64_t cur_video_time; + struct video_frame *cur_frame; + struct video_frame *next_frame; + event_t update_event; + uint64_t frame_time; + volatile uint64_t cur_video_time; - bool initialized; + bool initialized; + + pthread_mutex_t input_mutex; + DARRAY(struct video_input) inputs; }; /* ------------------------------------------------------------------------- */ @@ -54,6 +62,22 @@ static inline void video_swapframes(struct video_output *video) pthread_mutex_unlock(&video->data_mutex); } +static inline void video_output_cur_frame(struct video_output *video) +{ + if (!video->cur_frame) + return; + + pthread_mutex_lock(&video->input_mutex); + + /* TODO: conversion */ + for (size_t i = 0; i < video->inputs.num; i++) { + struct video_input *input = video->inputs.array+i; + input->callback(input->param, video->cur_frame); + } + + pthread_mutex_unlock(&video->input_mutex); +} + static void *video_thread(void *param) { struct video_output *video = param; @@ -68,8 +92,7 @@ static void *video_thread(void *param) /* wait another half a frame, swap and output frames */ os_sleepto_ns(cur_time += (video->frame_time/2)); video_swapframes(video); - if (video->cur_frame) - media_output_data(video->output, video->cur_frame); + video_output_cur_frame(video); } return NULL; @@ -77,27 +100,13 @@ static void *video_thread(void *param) /* ------------------------------------------------------------------------- */ -static inline bool valid_video_params(struct video_info *info) +static inline bool valid_video_params(struct video_output_info *info) { return info->height != 0 && info->width != 0 && info->fps_den != 0 && info->fps_num != 0; } -static inline bool vo_add_to_media(video_t video) -{ - struct media_output_info oi; - oi.obj = video; - oi.connect = NULL; - - video->output = media_output_create(&oi); - if (!video->output) - return false; - - media_add_output(video->media, video->output); - return true; -} - -int video_output_open(video_t *video, media_t media, struct video_info *info) +int video_output_open(video_t *video, struct video_output_info *info) { struct video_output *out; @@ -110,17 +119,16 @@ int video_output_open(video_t *video, media_t media, struct video_info *info) memcpy(&out->info, info, sizeof(struct video_info)); out->frame_time = (uint64_t)(1000000000.0 * (double)info->fps_den / (double)info->fps_num); - out->media = media; out->initialized = false; if (pthread_mutex_init(&out->data_mutex, NULL) != 0) goto fail; + if (pthread_mutex_init(&out->input_mutex, NULL) != 0) + goto fail; if (event_init(&out->stop_event, EVENT_TYPE_MANUAL) != 0) goto fail; if (event_init(&out->update_event, EVENT_TYPE_AUTO) != 0) goto fail; - if (!vo_add_to_media(out)) - goto fail; if (pthread_create(&out->thread, NULL, video_thread, out) != 0) goto fail; @@ -133,7 +141,74 @@ fail: return VIDEO_OUTPUT_FAIL; } -const struct video_info *video_output_getinfo(video_t video) +void video_output_close(video_t video) +{ + if (!video) + return; + + video_output_stop(video); + + da_free(video->inputs); + event_destroy(&video->update_event); + event_destroy(&video->stop_event); + pthread_mutex_destroy(&video->data_mutex); + pthread_mutex_destroy(&video->input_mutex); + bfree(video); +} + +static size_t video_get_input_idx(video_t video, + void (*callback)(void *param, struct video_frame *frame), + void *param) +{ + for (size_t i = 0; i < video->inputs.num; i++) { + struct video_input *input = video->inputs.array+i; + if (input->callback == callback && input->param == param) + return i; + } + + return DARRAY_INVALID; +} + +void video_output_connect(video_t video, struct video_info *format, + void (*callback)(void *param, struct video_frame *frame), + void *param) +{ + pthread_mutex_lock(&video->input_mutex); + + if (video_get_input_idx(video, callback, param) != DARRAY_INVALID) { + struct video_input input; + input.callback = callback; + input.param = param; + + /* TODO: conversion */ + if (format) { + input.format = *format; + } else { + input.format.type = video->info.type; + input.format.height = video->info.height; + input.format.width = video->info.width; + } + + da_push_back(video->inputs, &input); + } + + pthread_mutex_unlock(&video->input_mutex); +} + +void video_output_disconnect(video_t video, + void (*callback)(void *param, struct video_frame *frame), + void *param) +{ + pthread_mutex_lock(&video->input_mutex); + + size_t idx = video_get_input_idx(video, callback, param); + if (idx != DARRAY_INVALID) + da_erase(video->inputs, idx); + + pthread_mutex_unlock(&video->input_mutex); +} + +const struct video_output_info *video_output_getinfo(video_t video) { return &video->info; } @@ -174,21 +249,3 @@ void video_output_stop(video_t video) event_signal(&video->update_event); } } - -void video_output_close(video_t video) -{ - if (!video) - return; - - video_output_stop(video); - - if (video->output) { - media_remove_output(video->media, video->output); - media_output_destroy(video->output); - } - - event_destroy(&video->update_event); - event_destroy(&video->stop_event); - pthread_mutex_destroy(&video->data_mutex); - bfree(video); -} diff --git a/libobs/media-io/video-io.h b/libobs/media-io/video-io.h index 1b053ee0b..ac2d9ef3f 100644 --- a/libobs/media-io/video-io.h +++ b/libobs/media-io/video-io.h @@ -18,16 +18,12 @@ #pragma once #include "../util/c99defs.h" -#include "media-io.h" #ifdef __cplusplus extern "C" { #endif -/* - * Base video output component. Use this to create an video output track - * for the media. - */ +/* Base video output component. Use this to create an video output track. */ struct video_output; typedef struct video_output *video_t; @@ -37,7 +33,7 @@ enum video_format { /* planar 420 format */ VIDEO_FORMAT_I420, /* three-plane */ - VIDEO_FORMAT_NV12, /* two-plane, lum and packed chroma */ + VIDEO_FORMAT_NV12, /* two-plane, luma and packed chroma */ /* packed 422 formats */ VIDEO_FORMAT_YVYU, @@ -54,33 +50,47 @@ enum video_format { struct video_frame { const void *data; - uint32_t row_size; /* for RGB/BGR formats and UYVX */ + uint32_t row_size; /* for RGB/BGR formats and UYVX */ uint64_t timestamp; }; -struct video_info { +struct video_output_info { const char *name; enum video_format type; - uint32_t fps_num; /* numerator */ - uint32_t fps_den; /* denominator */ + uint32_t fps_num; + uint32_t fps_den; uint32_t width; uint32_t height; }; +struct video_info { + enum video_format type; + uint32_t width; + uint32_t height; + uint32_t row_size; /* if any */ +}; + #define VIDEO_OUTPUT_SUCCESS 0 #define VIDEO_OUTPUT_INVALIDPARAM -1 #define VIDEO_OUTPUT_FAIL -2 -EXPORT int video_output_open(video_t *video, media_t media, - struct video_info *info); -EXPORT const struct video_info *video_output_getinfo(video_t video); +EXPORT int video_output_open(video_t *video, struct video_output_info *info); +EXPORT void video_output_close(video_t video); + +EXPORT void video_output_connect(video_t video, struct video_info *format, + void (*callback)(void *param, struct video_frame *frame), + void *param); +EXPORT void video_output_disconnect(video_t video, + void (*callback)(void *param, struct video_frame *frame), + void *param); + +EXPORT const struct video_output_info *video_output_getinfo(video_t video); EXPORT void video_output_frame(video_t video, struct video_frame *frame); EXPORT bool video_output_wait(video_t video); EXPORT uint64_t video_getframetime(video_t video); EXPORT uint64_t video_gettime(video_t video); EXPORT void video_output_stop(video_t video); -EXPORT void video_output_close(video_t video); #ifdef __cplusplus } diff --git a/libobs/obs-data.h b/libobs/obs-data.h index c38aab985..f734d1495 100644 --- a/libobs/obs-data.h +++ b/libobs/obs-data.h @@ -22,7 +22,6 @@ #include "graphics/graphics.h" -#include "media-io/media-io.h" #include "media-io/video-io.h" #include "media-io/audio-io.h" @@ -86,8 +85,6 @@ struct obs_subsystem { DARRAY(struct output_info) output_types; DARRAY(struct service_info) service_types; - media_t media; - signal_handler_t signals; proc_handler_t procs; diff --git a/libobs/obs-source.c b/libobs/obs-source.c index 3402ee418..21746a3d2 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -323,8 +323,11 @@ void obs_source_video_tick(obs_source_t source, float seconds) static inline uint64_t conv_frames_to_time(obs_source_t source, size_t frames) { - const struct audio_info *info = audio_output_getinfo(obs->audio.audio); - double sps_to_ns = 1000000000.0 / (double)info->samples_per_sec; + const struct audio_output_info *info; + double sps_to_ns; + + info = audio_output_getinfo(obs->audio.audio); + sps_to_ns = 1000000000.0 / (double)info->samples_per_sec; return (uint64_t)((double)frames * sps_to_ns); } @@ -783,7 +786,7 @@ static inline struct filtered_audio *filter_async_audio(obs_source_t source, static inline void reset_resampler(obs_source_t source, const struct source_audio *audio) { - const struct audio_info *obs_info; + const struct audio_output_info *obs_info; struct resample_info output_info; obs_info = audio_output_getinfo(obs->audio.audio); diff --git a/libobs/obs-source.h b/libobs/obs-source.h index 5e7fe73bb..9409a40fc 100644 --- a/libobs/obs-source.h +++ b/libobs/obs-source.h @@ -21,7 +21,6 @@ #include "util/darray.h" #include "util/dstr.h" #include "util/threading.h" -#include "media-io/media-io.h" #include "media-io/audio-resampler.h" #include "callback/signal.h" #include "callback/proc.h" diff --git a/libobs/obs.c b/libobs/obs.c index 27d82cf2b..99dd36ebf 100644 --- a/libobs/obs.c +++ b/libobs/obs.c @@ -37,7 +37,7 @@ static inline void make_gs_init_data(struct gs_init_data *gid, gid->adapter = ovi->adapter; } -static inline void make_video_info(struct video_info *vi, +static inline void make_video_info(struct video_output_info *vi, struct obs_video_info *ovi) { vi->name = "video"; @@ -120,11 +120,11 @@ static bool obs_init_graphics(struct obs_video_info *ovi) static bool obs_init_video(struct obs_video_info *ovi) { struct obs_video *video = &obs->video; - struct video_info vi; + struct video_output_info vi; int errorcode; make_video_info(&vi, ovi); - errorcode = video_output_open(&video->video, obs->media, &vi); + errorcode = video_output_open(&video->video, &vi); if (errorcode != VIDEO_OUTPUT_SUCCESS) { if (errorcode == VIDEO_OUTPUT_INVALIDPARAM) @@ -195,14 +195,14 @@ static void obs_free_graphics() } } -static bool obs_init_audio(struct audio_info *ai) +static bool obs_init_audio(struct audio_output_info *ai) { struct obs_audio *audio = &obs->audio; int errorcode; /* TODO: sound subsystem */ - errorcode = audio_output_open(&audio->audio, obs->media, ai); + errorcode = audio_output_open(&audio->audio, ai); if (errorcode == AUDIO_OUTPUT_SUCCESS) return true; else if (errorcode == AUDIO_OUTPUT_INVALIDPARAM) @@ -277,18 +277,10 @@ static inline bool obs_init_handlers(void) static bool obs_init(void) { obs = bmalloc(sizeof(struct obs_subsystem)); - memset(obs, 0, sizeof(struct obs_subsystem)); + obs_init_data(); - - if (!obs_init_handlers()) - return false; - - obs->media = media_open(); - if (!obs->media) - return false; - - return true; + return obs_init_handlers(); } bool obs_startup() @@ -324,7 +316,6 @@ void obs_shutdown(void) obs_free_video(); obs_free_graphics(); obs_free_audio(); - media_close(obs->media); proc_handler_destroy(obs->procs); signal_handler_destroy(obs->signals); @@ -353,7 +344,7 @@ bool obs_reset_video(struct obs_video_info *ovi) return obs_init_video(ovi); } -bool obs_reset_audio(struct audio_info *ai) +bool obs_reset_audio(struct audio_output_info *ai) { obs_free_audio(); if(!ai) @@ -365,7 +356,7 @@ bool obs_reset_audio(struct audio_info *ai) bool obs_get_video_info(struct obs_video_info *ovi) { struct obs_video *video = &obs->video; - const struct video_info *info; + const struct video_output_info *info; if (!obs || !video->graphics) return false; @@ -384,16 +375,16 @@ bool obs_get_video_info(struct obs_video_info *ovi) return true; } -bool obs_get_audio_info(struct audio_info *ai) +bool obs_get_audio_info(struct audio_output_info *aoi) { struct obs_audio *audio = &obs->audio; - const struct audio_info *info; + const struct audio_output_info *info; if (!obs || !audio->audio) return false; info = audio_output_getinfo(audio->audio); - memcpy(ai, info, sizeof(struct audio_info)); + memcpy(aoi, info, sizeof(struct audio_output_info)); return true; } @@ -435,9 +426,14 @@ graphics_t obs_graphics(void) return (obs != NULL) ? obs->video.graphics : NULL; } -media_t obs_media(void) +audio_t obs_audio(void) { - return obs->media; + return (obs != NULL) ? obs->audio.audio : NULL; +} + +video_t obs_video(void) +{ + return (obs != NULL) ? obs->video.video : NULL; } bool obs_add_source(obs_source_t source) diff --git a/libobs/obs.h b/libobs/obs.h index 78e2aa204..78b9683df 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -21,7 +21,8 @@ #include "util/bmem.h" #include "graphics/graphics.h" #include "graphics/vec2.h" -#include "media-io/media-io.h" +#include "media-io/audio-io.h" +#include "media-io/video-io.h" #include "callback/signal.h" #include "callback/proc.h" @@ -173,13 +174,13 @@ EXPORT bool obs_reset_video(struct obs_video_info *ovi); * * NOTE: Cannot reset base audio if currently streaming/recording. */ -EXPORT bool obs_reset_audio(struct audio_info *ai); +EXPORT bool obs_reset_audio(struct audio_output_info *ai); /** Gets the current video settings, returns false if none */ EXPORT bool obs_get_video_info(struct obs_video_info *ovi); /** Gets the current audio settings, returns false if none */ -EXPORT bool obs_get_audio_info(struct audio_info *ai); +EXPORT bool obs_get_audio_info(struct audio_output_info *ai); /** * Loads a plugin module @@ -225,8 +226,8 @@ EXPORT bool obs_enum_output_types(size_t idx, const char **id); /** Gets the graphics context for this OBS context */ EXPORT graphics_t obs_graphics(void); -/** Get the media context for this OBS context (used for outputs) */ -EXPORT media_t obs_media(void); +EXPORT audio_t obs_audio(void); +EXPORT video_t obs_video(void); /** * Adds a source to the user source list and increments the reference counter diff --git a/obs/window-basic-main.cpp b/obs/window-basic-main.cpp index fed8de301..8e167bfef 100644 --- a/obs/window-basic-main.cpp +++ b/obs/window-basic-main.cpp @@ -262,7 +262,7 @@ bool OBSBasic::InitGraphics() bool OBSBasic::InitAudio() { /* TODO: load audio settings from config */ - struct audio_info ai; + struct audio_output_info ai; ai.name = "test"; ai.samples_per_sec = 44100; ai.format = AUDIO_FORMAT_16BIT; diff --git a/plugins/obs-outputs/obs-outputs.c b/plugins/obs-outputs/obs-outputs.c index 82af58b3c..6ce9ace17 100644 --- a/plugins/obs-outputs/obs-outputs.c +++ b/plugins/obs-outputs/obs-outputs.c @@ -1,6 +1,6 @@ #include "obs-outputs.h" -static const char *outputs[1] = {"rtmp_stream"}; +static const char *outputs[] = {"rtmp_stream"}; const char *enum_outputs(size_t idx) { diff --git a/vs/2013/libobs/libobs.vcxproj b/vs/2013/libobs/libobs.vcxproj index a0c7d31fd..481988a8e 100644 --- a/vs/2013/libobs/libobs.vcxproj +++ b/vs/2013/libobs/libobs.vcxproj @@ -42,7 +42,6 @@ - @@ -90,7 +89,6 @@ - diff --git a/vs/2013/libobs/libobs.vcxproj.filters b/vs/2013/libobs/libobs.vcxproj.filters index e9e10deaf..e79d369ce 100644 --- a/vs/2013/libobs/libobs.vcxproj.filters +++ b/vs/2013/libobs/libobs.vcxproj.filters @@ -87,9 +87,6 @@ media-io\Header Files - - media-io\Header Files - media-io\Header Files @@ -227,9 +224,6 @@ media-io\Source Files - - media-io\Source Files - util\Source Files