obs-studio/test/test-input/sync-async-source.c
jp9000 f53df7da64 clang-format: Apply formatting
Code submissions have continually suffered from formatting
inconsistencies that constantly have to be addressed.  Using
clang-format simplifies this by making code formatting more consistent,
and allows automation of the code formatting so that maintainers can
focus more on the code itself instead of code formatting.
2019-06-23 23:49:10 -07:00

143 lines
3 KiB
C

#include <stdlib.h>
#include <util/threading.h>
#include <util/platform.h>
#include <obs.h>
struct async_sync_test {
obs_source_t *source;
os_event_t *stop_signal;
pthread_t thread;
bool initialized;
};
/* middle C */
static const double rate = 261.63 / 48000.0;
#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795
#endif
#define M_PI_X2 M_PI * 2
static const char *ast_getname(void *unused)
{
UNUSED_PARAMETER(unused);
return "Sync Test (Async Video/Audio Source)";
}
static void ast_destroy(void *data)
{
struct async_sync_test *ast = data;
if (ast->initialized) {
os_event_signal(ast->stop_signal);
pthread_join(ast->thread, NULL);
}
os_event_destroy(ast->stop_signal);
bfree(ast);
}
static inline void fill_texture(uint32_t *pixels, uint32_t color)
{
size_t x, y;
for (y = 0; y < 20; y++) {
for (x = 0; x < 20; x++) {
pixels[y * 20 + x] = color;
}
}
}
static void *video_thread(void *data)
{
struct async_sync_test *ast = data;
uint32_t sample_rate = audio_output_get_sample_rate(obs_get_audio());
uint32_t *pixels = bmalloc(20 * 20 * sizeof(uint32_t));
float *samples = bmalloc(sample_rate * sizeof(float));
uint64_t cur_time = os_gettime_ns();
bool whitelist = false;
double cos_val = 0.0;
uint64_t start_time = cur_time;
struct obs_source_frame frame = {
.data = {[0] = (uint8_t *)pixels},
.linesize = {[0] = 20 * 4},
.width = 20,
.height = 20,
.format = VIDEO_FORMAT_BGRX,
};
struct obs_source_audio audio = {
.speakers = SPEAKERS_MONO,
.data = {[0] = (uint8_t *)samples},
.samples_per_sec = sample_rate,
.frames = sample_rate,
.format = AUDIO_FORMAT_FLOAT,
};
while (os_event_try(ast->stop_signal) == EAGAIN) {
fill_texture(pixels, whitelist ? 0xFFFFFFFF : 0xFF000000);
frame.timestamp = cur_time - start_time;
audio.timestamp = cur_time - start_time;
if (whitelist) {
for (size_t i = 0; i < sample_rate; i++) {
cos_val += rate * M_PI_X2;
if (cos_val > M_PI_X2)
cos_val -= M_PI_X2;
samples[i] = (float)(cos(cos_val) * 0.5);
}
} else {
for (size_t i = 0; i < sample_rate; i++)
samples[i] = 0.0f;
}
obs_source_output_video(ast->source, &frame);
obs_source_output_audio(ast->source, &audio);
os_sleepto_ns(cur_time += 1000000000);
whitelist = !whitelist;
}
bfree(pixels);
bfree(samples);
return NULL;
}
static void *ast_create(obs_data_t *settings, obs_source_t *source)
{
struct async_sync_test *ast = bzalloc(sizeof(struct async_sync_test));
ast->source = source;
if (os_event_init(&ast->stop_signal, OS_EVENT_TYPE_MANUAL) != 0) {
ast_destroy(ast);
return NULL;
}
if (pthread_create(&ast->thread, NULL, video_thread, ast) != 0) {
ast_destroy(ast);
return NULL;
}
ast->initialized = true;
UNUSED_PARAMETER(settings);
UNUSED_PARAMETER(source);
return ast;
}
struct obs_source_info async_sync_test = {
.id = "async_sync_test",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_ASYNC_VIDEO | OBS_SOURCE_AUDIO,
.get_name = ast_getname,
.create = ast_create,
.destroy = ast_destroy,
};