lulzsun / libobs-sharp

A simple .NET library that provides bindings for libobs
MIT License
21 stars 2 forks source link

Error on libobs reset video: -3 (Invalid Parameter) #3

Open Osiris-Team opened 1 month ago

Osiris-Team commented 1 month ago

@lulzsun I am currently porting this bad boy over to Java and encountering the error above. Any help would be really appreciated! Log:

libobs version: 29.1.2
info: CPU Name: AMD Ryzen 9 5950X 16-Core Processor            
info: CPU Speed: 3400MHz
info: Physical Cores: 16, Logical Cores: 32
info: Physical Memory: 16308MB Total, 2991MB Free
info: Windows Version: 10.0 Build 22631 (release: 23H2; revision: 3880; 64-bit)
info: Running as administrator: false
info: Windows 10/11 Gaming Features:
info:   Game DVR: On
info:   Game Mode: Probably On (no reg key set)
info: Sec. Software Status:
info:   Microsoft Defender Antivirus: enabled (AV)
info:   Windows-Firewall: enabled (FW)
info: ---------------------------------
info: audio settings reset:
    samples per sec: 44100
    speakers:        2
    max buffering:   1044 milliseconds
    buffering type:  dynamically increasing
Audio reset result: true
Error on libobs reset video: -3 (Invalid Parameter)
Failed to get current video info
Exception in thread "main" java.lang.RuntimeException: Failed to reset video
    at com.osiris.sandbox.LibOBS.main(LibOBS.java:158)

Process finished with exit code 1
Show code ```java package com.osiris.sandbox; import com.sun.jna.*; import java.io.File; import java.util.*; public class LibOBS { static { String path = System.getProperty("jna.library.path"); path += File.pathSeparator + "C:\\Program Files (x86)\\obs-studio\\bin\\64bit" + File.pathSeparator + "C:\\Program Files (x86)\\obs-studio\\obs-plugins\\64bit"; System.setProperty("jna.library.path", path); } public interface ObsLibrary extends Library { ObsLibrary INSTANCE = Native.load("obs", ObsLibrary.class); String obs_get_version_string(); boolean obs_initialized(); boolean obs_startup(String locale, String module_config_path, Pointer profiler_name); void obs_shutdown(); void obs_add_data_path(String path); void obs_add_module_path(String bin_path, String data_path); boolean obs_reset_audio(obs_audio_info avi); int obs_reset_video(obs_video_info ovi); void obs_load_all_modules(); void obs_log_loaded_modules(); void obs_post_load_modules(); Pointer obs_source_create(String id, String name, Pointer settings, Pointer hotkey_data); void obs_set_output_source(int channel, Pointer source); Pointer obs_data_create(); void obs_data_set_bool(Pointer data, String name, boolean value); void obs_data_set_string(Pointer data, String name, String value); void obs_data_set_int(Pointer data, String name, long value); Pointer obs_video_encoder_create(String id, String name, Pointer settings, Pointer hotkey_data); void obs_encoder_set_video(Pointer encoder, Pointer video); void obs_data_release(Pointer data); Pointer obs_audio_encoder_create(String id, String name, Pointer settings, long track, Pointer hotkey_data); void obs_encoder_set_audio(Pointer encoder, Pointer audio); Pointer obs_output_create(String id, String name, Pointer settings, Pointer hotkey_data); void obs_output_set_video_encoder(Pointer output, Pointer encoder); void obs_output_set_audio_encoder(Pointer output, Pointer encoder, long track); boolean obs_output_start(Pointer output); String obs_output_get_last_error(Pointer output); Pointer obs_output_get_proc_handler(Pointer output); String obs_output_get_id(Pointer output); Pointer obs_get_video(); int obs_get_video_info(obs_video_info ovi); } public static class VideoResetError { public static final int OBS_VIDEO_SUCCESS = 0; public static final int OBS_VIDEO_FAIL = -1; public static final int OBS_VIDEO_NOT_SUPPORTED = -2; public static final int OBS_VIDEO_INVALID_PARAM = -3; public static final int OBS_VIDEO_CURRENTLY_ACTIVE = -4; public static final int OBS_VIDEO_MODULE_NOT_FOUND = -5; public static String getErrorString(int error) { switch (error) { case OBS_VIDEO_SUCCESS: return "Success"; case OBS_VIDEO_FAIL: return "Fail"; case OBS_VIDEO_NOT_SUPPORTED: return "Not Supported"; case OBS_VIDEO_INVALID_PARAM: return "Invalid Parameter"; case OBS_VIDEO_CURRENTLY_ACTIVE: return "Video Currently Active"; case OBS_VIDEO_MODULE_NOT_FOUND: return "Module Not Found"; default: return "Unknown Error"; } } } public static class obs_audio_info extends Structure { public int samples_per_sec; public int speakers; @Override protected List getFieldOrder() { return Arrays.asList("samples_per_sec", "speakers"); } } public static class obs_video_info extends Structure { public int adapter; public String graphics_module; public int fps_num; public int fps_den; public int base_width; public int base_height; public int output_width; public int output_height; public int output_format; public boolean gpu_conversion; public int colorspace; public int range; public int scale_type; @Override protected List getFieldOrder() { return Arrays.asList("adapter", "graphics_module", "fps_num", "fps_den", "base_width", "base_height", "output_width", "output_height", "output_format", "gpu_conversion", "colorspace", "range", "scale_type"); } } public static void main(String[] args) { ObsLibrary obs = ObsLibrary.INSTANCE; System.out.println("libobs version: " + obs.obs_get_version_string()); if (!obs.obs_startup("en-US", null, null)) { throw new RuntimeException("error on libobs startup"); } //obs.obs_add_data_path("./data/libobs/"); //obs.obs_add_module_path("./obs-plugins/64bit/", "./data/obs-plugins/%module%/"); obs_audio_info avi = new obs_audio_info(); avi.samples_per_sec = 44100; avi.speakers = 2; // Assuming SPEAKERS_STEREO is 2 boolean resetAudioCode = obs.obs_reset_audio(avi); System.out.println("Audio reset result: " + resetAudioCode); int mainWidth = 1280; // Reduced from 1920 int mainHeight = 720; // Reduced from 1080 obs_video_info ovi = new obs_video_info(); ovi.adapter = 0; ovi.graphics_module = "libobs-opengl"; // Assuming Linux environment ovi.fps_num = 60; ovi.fps_den = 1; ovi.base_width = mainWidth; ovi.base_height = mainHeight; ovi.output_width = mainWidth; ovi.output_height = mainHeight; ovi.output_format = 1; // Changed from 0 to 1 (NV12 to I420) ovi.gpu_conversion = true; ovi.colorspace = 0; // Assuming VIDEO_CS_DEFAULT is 0 ovi.range = 0; // Assuming VIDEO_RANGE_DEFAULT is 0 ovi.scale_type = 0; // Assuming OBS_SCALE_BILINEAR is 0 int resetVideoCode = obs.obs_reset_video(ovi); if (resetVideoCode != 0) { System.err.println("Error on libobs reset video: " + resetVideoCode + " (" + VideoResetError.getErrorString(resetVideoCode) + ")"); // Try to get current video info obs_video_info currentOvi = new obs_video_info(); int getVideoInfoResult = obs.obs_get_video_info(currentOvi); if (getVideoInfoResult == 0) { System.out.println("Current video settings:"); System.out.println("Base resolution: " + currentOvi.base_width + "x" + currentOvi.base_height); System.out.println("Output resolution: " + currentOvi.output_width + "x" + currentOvi.output_height); System.out.println("FPS: " + currentOvi.fps_num + "/" + currentOvi.fps_den); } else { System.err.println("Failed to get current video info"); } throw new RuntimeException("Failed to reset video"); } System.out.println("Video reset successful"); obs.obs_load_all_modules(); obs.obs_log_loaded_modules(); obs.obs_post_load_modules(); // The rest of the code (setting up sources, encoders, outputs) would follow here... System.out.println("Press Enter to exit..."); Scanner scanner = new Scanner(System.in); scanner.nextLine(); // Don't forget to shut down OBS obs.obs_shutdown(); } } ```
lulzsun commented 1 month ago

Hi, I've taken a look at your code and it seems like everything should work fine, so I am not sure what the issue may be.

My guess would be that there is an issue creating the obs_video_info object. I am not familiar with Java or the JNA library that you are using, but I'm guessing it may be related to JNA not correctly handling the initialization of the object.

https://github.com/obsproject/obs-studio/blob/1cb1864cc04e1036ea4066ee862f6ac88ea708d5/libobs/media-io/video-io.c#L226

static inline bool valid_video_params(const struct video_output_info *info)
{
    return info->height != 0 && info->width != 0 && info->fps_den != 0 &&
           info->fps_num != 0;
}

From what I can tell, it looks like you are initializing the object correctly; output_height, output_width, fps_den, and fps_num should be non-zero values. Could you maybe try to print out the properties of the object before calling obs_reset_video to double check if its valid?