diff --git a/libobs/media-io/audio-io.c b/libobs/media-io/audio-io.c index 7d4677ed1..5ac3444ab 100644 --- a/libobs/media-io/audio-io.c +++ b/libobs/media-io/audio-io.c @@ -38,8 +38,8 @@ struct audio_line { * buffer is depleted, it's destroyed */ bool alive; - struct audio_line **prev_next; - struct audio_line *next; + struct audio_line **prev_next; + struct audio_line *next; }; static inline void audio_line_destroy_data(struct audio_line *line) @@ -130,7 +130,7 @@ static void mix_audio_lines(struct audio_output *audio, uint64_t audio_time, while (line) { struct audio_line *next = line->next; - if (line->base_timestamp < prev_time) { + if (line->buffer.size && line->base_timestamp < prev_time) { clear_excess_audio_data(line, line->base_timestamp - prev_time); line->base_timestamp = prev_time; @@ -222,7 +222,7 @@ 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, true) != 0) + if (event_init(&out->stop_event, EVENT_TYPE_MANUAL) != 0) goto fail; if (!ao_add_to_media(out)) goto fail; @@ -243,6 +243,7 @@ audio_line_t audio_output_createline(audio_t audio, const char *name) struct audio_line *line = bmalloc(sizeof(struct audio_line)); memset(line, 0, sizeof(struct audio_line)); line->alive = true; + line->audio = audio; if (pthread_mutex_init(&line->mutex, NULL) != 0) { blog(LOG_ERROR, "audio_output_createline: Failed to create " @@ -393,8 +394,8 @@ static inline void mul_vol_float(struct audio_line *line, float volume, static void audio_line_place_data(struct audio_line *line, const struct audio_data *data, size_t position) { - size_t total_size = data->frames * line->audio->block_size; size_t total_num = data->frames * line->audio->channels; + size_t total_size = data->frames * line->audio->block_size; da_copy_array(line->volume_buffer, data->data, total_size); diff --git a/libobs/media-io/video-io.c b/libobs/media-io/video-io.c index 82d0821f4..be8701fe4 100644 --- a/libobs/media-io/video-io.c +++ b/libobs/media-io/video-io.c @@ -115,9 +115,9 @@ int video_output_open(video_t *video, media_t media, struct video_info *info) if (pthread_mutex_init(&out->data_mutex, NULL) != 0) goto fail; - if (event_init(&out->stop_event, true) != 0) + if (event_init(&out->stop_event, EVENT_TYPE_MANUAL) != 0) goto fail; - if (event_init(&out->update_event, false) != 0) + if (event_init(&out->update_event, EVENT_TYPE_AUTO) != 0) goto fail; if (!vo_add_to_media(out)) goto fail; diff --git a/libobs/obs-source.c b/libobs/obs-source.c index baf6bd9f6..8ee980447 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -332,14 +332,6 @@ static void source_output_audio_line(obs_source_t source, { struct audio_data in = *data; - if (!in.timestamp) { - in.timestamp = os_gettime_ns(); - if (!source->timing_set) { - source->timing_set = true; - source->timing_adjust = 0; - } - } - if (!source->timing_set) { source->timing_set = true; source->timing_adjust = in.timestamp - os_gettime_ns(); diff --git a/libobs/util/threading.h b/libobs/util/threading.h index 75e115562..e2f4955f5 100644 --- a/libobs/util/threading.h +++ b/libobs/util/threading.h @@ -53,9 +53,14 @@ struct event_data { bool manual; }; +enum event_type { + EVENT_TYPE_AUTO, + EVENT_TYPE_MANUAL +}; + typedef struct event_data event_t; -static inline int event_init(event_t *event, bool manual) +static inline int event_init(event_t *event, enum event_type type) { int code = 0; @@ -65,7 +70,7 @@ static inline int event_init(event_t *event, bool manual) if ((code = pthread_cond_init(&event->cond, NULL)) < 0) pthread_mutex_destroy(&event->mutex); - event->manual = manual; + event->manual = (type == EVENT_TYPE_MANUAL); event->signalled = false; return code; diff --git a/test/test-input/CMakeLists.txt b/test/test-input/CMakeLists.txt index c981e885a..abc564407 100644 --- a/test/test-input/CMakeLists.txt +++ b/test/test-input/CMakeLists.txt @@ -3,6 +3,7 @@ include_directories(SYSTEM ${obs_SOURCE_DIR}/libobs) add_library(test-input MODULE test-filter.c test-input.c + test-sinewave.c test-random.c) target_link_libraries(test-input diff --git a/test/test-input/makefile.am b/test/test-input/makefile.am index c0b5bf863..14d3645c5 100644 --- a/test/test-input/makefile.am +++ b/test/test-input/makefile.am @@ -19,4 +19,5 @@ endif libtest_input_la_LIBADD = $(top_srcdir)/libobs/libobs.la libtest_input_la_SOURCES = test-filter.c \ test-input.c \ - test-random.c + test-random.c \ + test-sinewave.c diff --git a/test/test-input/test-input.c b/test/test-input/test-input.c index e28ddb638..c1d79eb4a 100644 --- a/test/test-input/test-input.c +++ b/test/test-input/test-input.c @@ -1,7 +1,7 @@ #include #include "test-input-exports.h" -const char *inputs[] = {"random"}; +const char *inputs[] = {"random", "sinewave"}; const char *filters[] = {"test"}; uint32_t module_version(uint32_t in_version) diff --git a/test/test-input/test-random.c b/test/test-input/test-random.c index 7d56cceea..41a70fce5 100644 --- a/test/test-input/test-random.c +++ b/test/test-input/test-random.c @@ -3,7 +3,7 @@ const char *random_getname(const char *locale) { - return "Random Source"; + return "20x20 Random Pixel Texture Source (Test)"; } struct random_tex *random_create(const char *settings, obs_source_t source) diff --git a/test/test-input/test-sinewave.c b/test/test-input/test-sinewave.c new file mode 100644 index 000000000..ef040798b --- /dev/null +++ b/test/test-input/test-sinewave.c @@ -0,0 +1,86 @@ +#include +#include "test-sinewave.h" + +const double rate = 261.63/48000.0; + +#define M_PI 3.1415926535897932384626433832795 + +static void *sinewave_thread(void *pdata) +{ + struct sinewave_data *swd = pdata; + uint64_t last_time = os_gettime_ns(); + uint64_t ts = 0; + double sin_val = 0.0; + uint8_t bytes[480]; + + while (event_try(&swd->event) == EAGAIN) { + os_sleepto_ns(last_time += 10000000); + + for (size_t i = 0; i < 480; i++) { + sin_val += rate * M_PI; + if (sin_val > M_PI) + sin_val -= M_PI; + + double wave = sin(sin_val); + bytes[i] = (uint8_t)(wave * 255.0); + } + + struct source_audio data; + data.data = bytes; + data.frames = 480; + data.speakers = SPEAKERS_MONO; + data.samples_per_sec = 48000; + data.timestamp = ts; + data.format = AUDIO_FORMAT_U8BIT; + obs_source_output_audio(swd->source, &data); + + ts += 10000000; + } + + return NULL; +} + +/* ------------------------------------------------------------------------- */ + +const char *sinewave_getname(const char *locale) +{ + return "Sinewave Sound Source (Test)"; +} + +struct sinewave_data *sinewave_create(const char *settings, obs_source_t source) +{ + struct sinewave_data *swd = bmalloc(sizeof(struct sinewave_data)); + memset(swd, 0, sizeof(struct sinewave_data)); + swd->source = source; + + if (event_init(&swd->event, EVENT_TYPE_MANUAL) != 0) + goto fail; + if (pthread_create(&swd->thread, NULL, sinewave_thread, swd) != 0) + goto fail; + + swd->initialized_thread = true; + return swd; + +fail: + sinewave_destroy(swd); + return NULL; +} + +void sinewave_destroy(struct sinewave_data *swd) +{ + if (swd) { + if (swd->initialized_thread) { + void *ret; + event_signal(&swd->event); + pthread_join(swd->thread, &ret); + } + + event_destroy(&swd->event); + bfree(swd); + } +} + +uint32_t sinewave_get_output_flags(struct sinewave_data *swd) +{ + return SOURCE_AUDIO; +} diff --git a/test/test-input/test-sinewave.h b/test/test-input/test-sinewave.h new file mode 100644 index 000000000..5984a1071 --- /dev/null +++ b/test/test-input/test-sinewave.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct sinewave_data { + bool initialized_thread; + pthread_t thread; + event_t event; + obs_source_t source; +}; + +EXPORT const char *sinewave_getname(const char *locale); + +EXPORT struct sinewave_data *sinewave_create(const char *settings, + obs_source_t source); +EXPORT void sinewave_destroy(struct sinewave_data *swd); +EXPORT uint32_t sinewave_get_output_flags(struct sinewave_data *swd); + +#ifdef __cplusplus +} +#endif diff --git a/vs/2013/test-input/test-input.vcxproj b/vs/2013/test-input/test-input.vcxproj index 4ee2ffe3d..0d9dff498 100644 --- a/vs/2013/test-input/test-input.vcxproj +++ b/vs/2013/test-input/test-input.vcxproj @@ -22,11 +22,13 @@ + + {760ECBBC-EA7C-464A-B60E-945A0BB1B100} @@ -102,7 +104,7 @@ Windows true $(OutDir);%(AdditionalLibraryDirectories) - libobs.lib;%(AdditionalDependencies) + pthreads.lib;libobs.lib;%(AdditionalDependencies) copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/plugins/32bit/$(TargetName)$(TargetExt)" @@ -122,7 +124,7 @@ Windows true $(OutDir);%(AdditionalLibraryDirectories) - libobs.lib;%(AdditionalDependencies) + pthreads.lib;libobs.lib;%(AdditionalDependencies) copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/plugins/64bit/$(TargetName)$(TargetExt)" @@ -146,7 +148,7 @@ true true $(OutDir);%(AdditionalLibraryDirectories) - libobs.lib;%(AdditionalDependencies) + pthreads.lib;libobs.lib;%(AdditionalDependencies) copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/plugins/32bit/$(TargetName)$(TargetExt)" @@ -170,7 +172,7 @@ true true $(OutDir);%(AdditionalLibraryDirectories) - libobs.lib;%(AdditionalDependencies) + pthreads.lib;libobs.lib;%(AdditionalDependencies) copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/plugins/64bit/$(TargetName)$(TargetExt)" diff --git a/vs/2013/test-input/test-input.vcxproj.filters b/vs/2013/test-input/test-input.vcxproj.filters index c3dfeb37d..cb0e6f51e 100644 --- a/vs/2013/test-input/test-input.vcxproj.filters +++ b/vs/2013/test-input/test-input.vcxproj.filters @@ -24,6 +24,9 @@ Header Files + + Header Files + @@ -35,5 +38,8 @@ Source Files + + Source Files + \ No newline at end of file