diff --git a/libobs/graphics/graphics.c b/libobs/graphics/graphics.c index 4fc32dead..5c60d5def 100644 --- a/libobs/graphics/graphics.c +++ b/libobs/graphics/graphics.c @@ -809,13 +809,16 @@ void gs_draw_cube_backdrop(texture_t cubetex, const struct quat *rot, void gs_resetviewport(void) { uint32_t cx, cy; + assert(thread_graphics != NULL); gs_getsize(&cx, &cy); + gs_setviewport(0, 0, (int)cx, (int)cy); } void gs_set2dmode(void) { uint32_t cx, cy; + assert(thread_graphics != NULL); gs_getsize(&cx, &cy); gs_ortho(0.0f, (float)cx, 0.0f, (float)cy, -1.0, -1024.0f); diff --git a/libobs/media-io/audio-io.c b/libobs/media-io/audio-io.c index eb2c209af..d813b2eb6 100644 --- a/libobs/media-io/audio-io.c +++ b/libobs/media-io/audio-io.c @@ -575,6 +575,8 @@ int audio_output_open(audio_t *audio, struct audio_output_info *info) return AUDIO_OUTPUT_INVALIDPARAM; out = bzalloc(sizeof(struct audio_output)); + if (!out) + goto fail; memcpy(&out->info, info, sizeof(struct audio_output_info)); pthread_mutex_init_value(&out->line_mutex); diff --git a/libobs/media-io/video-io.c b/libobs/media-io/video-io.c index 5af5ad359..085e10748 100644 --- a/libobs/media-io/video-io.c +++ b/libobs/media-io/video-io.c @@ -165,6 +165,8 @@ int video_output_open(video_t *video, struct video_output_info *info) return VIDEO_OUTPUT_INVALIDPARAM; out = bzalloc(sizeof(struct video_output)); + if (!out) + goto fail; memcpy(&out->info, info, sizeof(struct video_output_info)); out->frame_time = (uint64_t)(1000000000.0 * (double)info->fps_den / diff --git a/libobs/obs-encoder.c b/libobs/obs-encoder.c index af7935b94..ee4056343 100644 --- a/libobs/obs-encoder.c +++ b/libobs/obs-encoder.c @@ -366,7 +366,6 @@ void obs_encoder_start(obs_encoder_t encoder, void *param) { struct encoder_callback cb = {false, new_packet, param}; - bool success = true; bool first = false; if (!encoder || !new_packet || !encoder->data) return; @@ -375,13 +374,9 @@ void obs_encoder_start(obs_encoder_t encoder, first = (encoder->callbacks.num == 0); - if (success) { - size_t idx = get_callback_idx(encoder, new_packet, param); - if (idx == DARRAY_INVALID) - da_push_back(encoder->callbacks, &cb); - else - success = false; - } + size_t idx = get_callback_idx(encoder, new_packet, param); + if (idx == DARRAY_INVALID) + da_push_back(encoder->callbacks, &cb); pthread_mutex_unlock(&encoder->callbacks_mutex); diff --git a/libobs/obs-scene.c b/libobs/obs-scene.c index fbe31870e..fe7c8e146 100644 --- a/libobs/obs-scene.c +++ b/libobs/obs-scene.c @@ -130,6 +130,8 @@ static inline void attach_sceneitem(struct obs_scene_item *item, prev->next->prev = item; prev->next = item; } else { + assert(item->parent != NULL); + item->next = item->parent->first_item; item->parent->first_item = item; } @@ -406,6 +408,8 @@ void obs_sceneitem_remove(obs_sceneitem_t item) item->removed = true; + assert(scene != NULL); + assert(scene->source != NULL); obs_source_remove_child(scene->source, item->source); signal_item_remove(item); diff --git a/libobs/obs.c b/libobs/obs.c index 466b6e67c..194eaa309 100644 --- a/libobs/obs.c +++ b/libobs/obs.c @@ -387,6 +387,8 @@ static bool obs_init_data(void) struct obs_core_data *data = &obs->data; pthread_mutexattr_t attr; + assert(data != NULL); + pthread_mutex_init_value(&obs->data.displays_mutex); if (pthread_mutexattr_init(&attr) != 0) diff --git a/libobs/util/config-file.c b/libobs/util/config-file.c index be9e77279..7466caa31 100644 --- a/libobs/util/config-file.c +++ b/libobs/util/config-file.c @@ -234,6 +234,9 @@ int config_open(config_t *config, const char *file, return CONFIG_ERROR; *config = bzalloc(sizeof(struct config_data)); + if (!*config) + return CONFIG_ERROR; + (*config)->file = bstrdup(file); errorcode = config_parse(&(*config)->sections, file, always_open); diff --git a/libobs/util/platform-cocoa.m b/libobs/util/platform-cocoa.m index a70b19ed8..e5f99ca9f 100644 --- a/libobs/util/platform-cocoa.m +++ b/libobs/util/platform-cocoa.m @@ -87,14 +87,43 @@ void os_sleep_ms(uint32_t duration) usleep(duration*1000); } + +/* clock function selection taken from libc++ */ +static uint64_t ns_time_simple() +{ + return mach_absolute_time(); +} + +static double ns_time_compute_factor() +{ + mach_timebase_info_data_t info = {1, 1}; + mach_timebase_info(&info); + return ((double)info.numer) / info.denom; +} + +static uint64_t ns_time_full() +{ + static double factor = 0.; + if (factor == 0.) factor = ns_time_compute_factor(); + return (uint64_t)(mach_absolute_time() * factor); +} + +typedef uint64_t (*time_func)(); + +static time_func ns_time_select_func() +{ + mach_timebase_info_data_t info = {1, 1}; + mach_timebase_info(&info); + if (info.denom == info.numer) + return ns_time_simple; + return ns_time_full; +} + uint64_t os_gettime_ns(void) { - uint64_t t = mach_absolute_time(); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - Nanoseconds nano = AbsoluteToNanoseconds(*(AbsoluteTime*) &t); -#pragma clang diagnostic pop - return *(uint64_t*) &nano; + static time_func f = NULL; + if (!f) f = ns_time_select_func(); + return f(); } /* gets the location ~/Library/Application Support/[name] */ diff --git a/libobs/util/threading-posix.c b/libobs/util/threading-posix.c index cbbc56922..a86f1ac71 100644 --- a/libobs/util/threading-posix.c +++ b/libobs/util/threading-posix.c @@ -171,6 +171,9 @@ int os_sem_init(os_sem_t *sem, int value) return -1; *sem = bzalloc(sizeof(struct os_sem_data)); + if (!*sem) + return -2; + (*sem)->sem = new_sem; (*sem)->task = task; return 0; diff --git a/libobs/util/threading.h b/libobs/util/threading.h index e525cf82f..d48306b0c 100644 --- a/libobs/util/threading.h +++ b/libobs/util/threading.h @@ -40,6 +40,9 @@ extern "C" { /* this may seem strange, but you can't use it unless it's an initializer */ static inline void pthread_mutex_init_value(pthread_mutex_t *mutex) { + if (!mutex) + return; + pthread_mutex_t init_val = PTHREAD_MUTEX_INITIALIZER; *mutex = init_val; } diff --git a/test/osx/test.mm b/test/osx/test.mm index 352cb0acf..bc346d538 100644 --- a/test/osx/test.mm +++ b/test/osx/test.mm @@ -14,15 +14,13 @@ static const int cx = 800; static const int cy = 600; - - /* --------------------------------------------------- */ template struct OBSUniqueHandle : std::unique_ptr> { using base = std::unique_ptr>; - explicit OBSUniqueHandle(T *obj) : base(obj, D) {} + explicit OBSUniqueHandle(T *obj=nullptr) : base(obj, D) {} operator T*() { return base::get(); } }; @@ -38,7 +36,7 @@ using SceneContext = OBSUniqueHandle +{ + NSWindow *win; + NSView *view; + SceneContext scene; +} +- (void)applicationDidFinishLaunching:(NSNotification*)notification; +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)app; +- (void)windowWillClose:(NSNotification*)notification; @end -@implementation window_closer - -+(id)window_closer +@implementation OBSTest +- (void)applicationDidFinishLaunching:(NSNotification*)notification { - return [[window_closer alloc] init]; -} + UNUSED_PARAMETER(notification); --(void)windowWillClose:(NSNotification *)notification -{ - (void)notification; - [NSApp stop:self]; -} -@end - -static NSWindow *CreateTestWindow() -{ - [NSApplication sharedApplication]; - - ProcessSerialNumber psn = {0, kCurrentProcess}; - TransformProcessType(&psn, kProcessTransformToForegroundApplication); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - SetFrontProcess(&psn); -#pragma clang diagnostic pop - - NSRect content_rect = NSMakeRect(0, 0, cx, cy); - NSWindow *win = [[NSWindow alloc] - initWithContentRect:content_rect - styleMask:NSTitledWindowMask | NSClosableWindowMask - backing:NSBackingStoreBuffered - defer:NO]; - if(!win) - return nil; - - [win orderFrontRegardless]; - - NSView *view = [[NSView alloc] initWithFrame:content_rect]; - if(!view) - return nil; - - - [win setContentView:view]; - [win setTitle:@"foo"]; - [win center]; - [win makeMainWindow]; - [win setDelegate:[window_closer window_closer]]; - return win; -} - -/* --------------------------------------------------- */ - -static void RenderWindow(void *data, uint32_t cx, uint32_t cy) -{ - obs_render_main_view(); - - UNUSED_PARAMETER(data); - UNUSED_PARAMETER(cx); - UNUSED_PARAMETER(cy); -} - -/* --------------------------------------------------- */ - -static void test() -{ try { - static NSWindow *win = CreateTestWindow(); + NSRect content_rect = NSMakeRect(0, 0, cx, cy); + win = [[NSWindow alloc] + initWithContentRect:content_rect + styleMask:NSTitledWindowMask | NSClosableWindowMask + backing:NSBackingStoreBuffered + defer:NO]; if (!win) - throw "Couldn't create main window"; + throw "Could not create window"; - CreateOBS(win); + view = [[NSView alloc] initWithFrame:content_rect]; + if (!view) + throw "Could not create view"; - /* ------------------------------------------------------ */ - /* load module */ - if (obs_load_module("test-input") != 0) - throw "Couldn't load module"; + win.title = @"foo"; + win.delegate = self; + win.contentView = view; - /* ------------------------------------------------------ */ - /* create source */ - SourceContext source{obs_source_create(OBS_SOURCE_TYPE_INPUT, - "random", "a test source", NULL)}; - if (!source) - throw "Couldn't create random test source"; + [win orderFrontRegardless]; + [win center]; + [win makeMainWindow]; - /* ------------------------------------------------------ */ - /* create filter */ - SourceContext filter{obs_source_create(OBS_SOURCE_TYPE_FILTER, - "test_filter", "a test filter", NULL)}; - if (!filter) - throw "Couldn't create test filter"; - obs_source_filter_add(source, filter); + CreateOBS(view); - /* ------------------------------------------------------ */ - /* create scene and add source to scene (twice) */ - SceneContext scene{obs_scene_create("test scene")}; - if (!scene) - throw "Couldn't create scene"; + scene = SetupScene(); - AddTestItems(scene, source); - - /* ------------------------------------------------------ */ - /* set the scene as the primary draw source and go */ - obs_set_output_source(0, obs_scene_getsource(scene)); - - /* ------------------------------------------------------ */ - /* set the main output render callback */ - obs_add_draw_callback(RenderWindow, nullptr); - - [NSApp run]; - - obs_set_output_source(0, NULL); + obs_add_draw_callback( + [](void *, uint32_t, uint32_t) { + obs_render_main_view(); + }, nullptr); } catch (char const *error) { - printf("%s\n", error); + NSLog(@"%s\n", error); + + [NSApp terminate:nil]; } +} + +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)app +{ + UNUSED_PARAMETER(app); + + return YES; +} + +- (void)windowWillClose:(NSNotification*)notification +{ + UNUSED_PARAMETER(notification); + + obs_set_output_source(0, nullptr); + scene.reset(); obs_shutdown(); - - blog(LOG_INFO, "Number of memory leaks: %lu", bnum_allocs()); + NSLog(@"Number of memory leaks: %lu", bnum_allocs()); } +@end /* --------------------------------------------------- */ int main() { @autoreleasepool { - test(); + [NSApplication sharedApplication]; + OBSTest *test = [[OBSTest alloc] init]; + [NSApp setDelegate:test]; + + [NSApp run]; } return 0; diff --git a/test/test-input/test-desktop.m b/test/test-input/test-desktop.m index 7c95a1845..c71d454dd 100644 --- a/test/test-input/test-desktop.m +++ b/test/test-input/test-desktop.m @@ -91,10 +91,12 @@ static bool init_display_stream(struct display_capture *dc) NSNumber *screen_num = screen.deviceDescription[@"NSScreenNumber"]; CGDirectDisplayID disp_id = (CGDirectDisplayID)screen_num.pointerValue; + NSDictionary *rect_dict = CFBridgingRelease( + CGRectCreateDictionaryRepresentation( + CGRectMake(0, 0, dc->width, dc->height))); + NSDictionary *dict = @{ - (__bridge NSString*)kCGDisplayStreamSourceRect: - (__bridge NSDictionary*)CGRectCreateDictionaryRepresentation( - CGRectMake(0, 0, dc->width, dc->height)), + (__bridge NSString*)kCGDisplayStreamSourceRect: rect_dict, (__bridge NSString*)kCGDisplayStreamQueueDepth: @5 };