(API Change) obs_reset_video: Use return codes
Changed API functions: libobs: obs_reset_video Before, video initialization returned a boolean, but "failed" is too little information, if it fails due to lack of device capabilities or bad video device parameters, the front-end needs to know that. The OBS Basic UI has also been updated to reflect this API change.
This commit is contained in:
parent
e62f965d3e
commit
778cc2b318
@ -20,6 +20,13 @@
|
||||
#include <graphics/matrix3.h>
|
||||
#include "d3d11-subsystem.hpp"
|
||||
|
||||
struct UnsupportedHWError : HRError {
|
||||
inline UnsupportedHWError(const char *str, HRESULT hr)
|
||||
: HRError(str, hr)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/* alignment warning - despite the fact that alignment is already fixed */
|
||||
#pragma warning (disable : 4316)
|
||||
@ -136,11 +143,11 @@ void gs_device::InitFactory(uint32_t adapterIdx, IDXGIAdapter1 **padapter)
|
||||
|
||||
hr = CreateDXGIFactory1(factoryIID, (void**)factory.Assign());
|
||||
if (FAILED(hr))
|
||||
throw HRError("Failed to create DXGIFactory", hr);
|
||||
throw UnsupportedHWError("Failed to create DXGIFactory", hr);
|
||||
|
||||
hr = factory->EnumAdapters1(adapterIdx, padapter);
|
||||
if (FAILED(hr))
|
||||
throw HRError("Failed to enumerate DXGIAdapter", hr);
|
||||
throw UnsupportedHWError("Failed to enumerate DXGIAdapter", hr);
|
||||
}
|
||||
|
||||
const static D3D_FEATURE_LEVEL featureLevels[] =
|
||||
@ -181,7 +188,8 @@ void gs_device::InitDevice(gs_init_data *data, IDXGIAdapter *adapter)
|
||||
defaultSwap.swap.Assign(), device.Assign(),
|
||||
&levelUsed, context.Assign());
|
||||
if (FAILED(hr))
|
||||
throw HRError("Failed to create device and swap chain", hr);
|
||||
throw UnsupportedHWError("Failed to create device and "
|
||||
"swap chain", hr);
|
||||
|
||||
blog(LOG_INFO, "D3D11 loaded sucessfully, feature level used: %u",
|
||||
(uint32_t)levelUsed);
|
||||
@ -433,18 +441,27 @@ const char *device_preprocessor_name(void)
|
||||
return "_D3D11";
|
||||
}
|
||||
|
||||
gs_device *device_create(gs_init_data *data)
|
||||
int device_create(device_t *p_device, gs_init_data *data)
|
||||
{
|
||||
gs_device *device = NULL;
|
||||
int errorcode = GS_SUCCESS;
|
||||
|
||||
try {
|
||||
device = new gs_device(data);
|
||||
|
||||
} catch (UnsupportedHWError error) {
|
||||
blog(LOG_ERROR, "device_create (D3D11): %s (%08lX)", error.str,
|
||||
error.hr);
|
||||
errorcode = GS_ERROR_NOT_SUPPORTED;
|
||||
|
||||
} catch (HRError error) {
|
||||
blog(LOG_ERROR, "device_create (D3D11): %s (%08lX)", error.str,
|
||||
error.hr);
|
||||
errorcode = GS_ERROR_FAIL;
|
||||
}
|
||||
|
||||
return device;
|
||||
*p_device = device;
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
void device_destroy(device_t device)
|
||||
|
@ -197,16 +197,19 @@ const char *device_preprocessor_name(void)
|
||||
return "_OPENGL";
|
||||
}
|
||||
|
||||
device_t device_create(struct gs_init_data *info)
|
||||
int device_create(device_t *p_device, struct gs_init_data *info)
|
||||
{
|
||||
struct gs_device *device = bzalloc(sizeof(struct gs_device));
|
||||
int errorcode = GS_ERROR_FAIL;
|
||||
|
||||
device->plat = gl_platform_create(device, info);
|
||||
if (!device->plat)
|
||||
goto fail;
|
||||
|
||||
if (!gl_init_extensions(device))
|
||||
if (!gl_init_extensions(device)) {
|
||||
errorcode = GS_ERROR_NOT_SUPPORTED;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
gl_enable(GL_CULL_FACE);
|
||||
|
||||
@ -221,12 +224,15 @@ device_t device_create(struct gs_init_data *info)
|
||||
device_leavecontext(device);
|
||||
device->cur_swap = gl_platform_getswap(device->plat);
|
||||
|
||||
return device;
|
||||
*p_device = device;
|
||||
return GS_SUCCESS;
|
||||
|
||||
fail:
|
||||
blog(LOG_ERROR, "device_create (GL) failed");
|
||||
bfree(device);
|
||||
return NULL;
|
||||
|
||||
*p_device = NULL;
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
void device_destroy(device_t device)
|
||||
|
@ -26,7 +26,7 @@ extern "C" {
|
||||
EXPORT const char *device_name(void);
|
||||
EXPORT int device_type(void);
|
||||
EXPORT const char *device_preprocessor_name(void);
|
||||
EXPORT device_t device_create(struct gs_init_data *data);
|
||||
EXPORT int device_create(device_t *device, struct gs_init_data *data);
|
||||
EXPORT void device_destroy(device_t device);
|
||||
EXPORT void device_entercontext(device_t device);
|
||||
EXPORT void device_leavecontext(device_t device);
|
||||
|
@ -27,7 +27,7 @@ struct gs_exports {
|
||||
const char *(*device_name)(void);
|
||||
int (*device_type)(void);
|
||||
const char *(*device_preprocessor_name)(void);
|
||||
device_t (*device_create)(struct gs_init_data *data);
|
||||
int (*device_create)(device_t *device, struct gs_init_data *data);
|
||||
void (*device_destroy)(device_t device);
|
||||
void (*device_entercontext)(device_t device);
|
||||
void (*device_leavecontext)(device_t device);
|
||||
|
@ -137,15 +137,17 @@ int gs_create(graphics_t *pgraphics, const char *module,
|
||||
module))
|
||||
goto error;
|
||||
|
||||
graphics->device = graphics->exports.device_create(data);
|
||||
if (!graphics->device)
|
||||
errcode = graphics->exports.device_create(&graphics->device, data);
|
||||
if (errcode != GS_SUCCESS)
|
||||
goto error;
|
||||
|
||||
if (!graphics_init(graphics))
|
||||
if (!graphics_init(graphics)) {
|
||||
errcode = GS_ERROR_FAIL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
*pgraphics = graphics;
|
||||
return GS_SUCCESS;
|
||||
return errcode;
|
||||
|
||||
error:
|
||||
gs_destroy(graphics);
|
||||
|
@ -392,8 +392,9 @@ EXPORT texture_t texrender_gettexture(texrender_t texrender);
|
||||
/* global functions */
|
||||
|
||||
#define GS_SUCCESS 0
|
||||
#define GS_ERROR_MODULE_NOT_FOUND -1
|
||||
#define GS_ERROR_FAIL -2
|
||||
#define GS_ERROR_FAIL -1
|
||||
#define GS_ERROR_MODULE_NOT_FOUND -2
|
||||
#define GS_ERROR_NOT_SUPPORTED -3
|
||||
|
||||
struct gs_window {
|
||||
#if defined(_WIN32)
|
||||
|
@ -38,3 +38,10 @@
|
||||
#define OBS_OUTPUT_INVALID_STREAM -3
|
||||
#define OBS_OUTPUT_ERROR -4
|
||||
#define OBS_OUTPUT_DISCONNECTED -5
|
||||
|
||||
#define OBS_VIDEO_SUCCESS 0
|
||||
#define OBS_VIDEO_FAIL -1
|
||||
#define OBS_VIDEO_NOT_SUPPORTED -2
|
||||
#define OBS_VIDEO_INVALID_PARAM -3
|
||||
#define OBS_VIDEO_CURRENTLY_ACTIVE -4
|
||||
#define OBS_VIDEO_MODULE_NOT_FOUND -5
|
||||
|
103
libobs/obs.c
103
libobs/obs.c
@ -192,7 +192,7 @@ static bool obs_init_textures(struct obs_video_info *ovi)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool obs_init_graphics(struct obs_video_info *ovi)
|
||||
static int obs_init_graphics(struct obs_video_info *ovi)
|
||||
{
|
||||
struct obs_core_video *video = &obs->video;
|
||||
struct gs_init_data graphics_data;
|
||||
@ -204,43 +204,45 @@ static bool obs_init_graphics(struct obs_video_info *ovi)
|
||||
errorcode = gs_create(&video->graphics, ovi->graphics_module,
|
||||
&graphics_data);
|
||||
if (errorcode != GS_SUCCESS) {
|
||||
if (errorcode == GS_ERROR_MODULE_NOT_FOUND)
|
||||
blog(LOG_ERROR, "Could not find graphics module '%s'",
|
||||
ovi->graphics_module);
|
||||
return false;
|
||||
switch (errorcode) {
|
||||
case GS_ERROR_MODULE_NOT_FOUND:
|
||||
return OBS_VIDEO_MODULE_NOT_FOUND;
|
||||
case GS_ERROR_NOT_SUPPORTED:
|
||||
return OBS_VIDEO_NOT_SUPPORTED;
|
||||
default:
|
||||
return OBS_VIDEO_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
gs_entercontext(video->graphics);
|
||||
|
||||
if (success) {
|
||||
char *filename = find_libobs_data_file("default.effect");
|
||||
video->default_effect = gs_create_effect_from_file(filename,
|
||||
NULL);
|
||||
bfree(filename);
|
||||
char *filename = find_libobs_data_file("default.effect");
|
||||
video->default_effect = gs_create_effect_from_file(filename,
|
||||
NULL);
|
||||
bfree(filename);
|
||||
|
||||
filename = find_libobs_data_file("solid.effect");
|
||||
video->solid_effect = gs_create_effect_from_file(filename,
|
||||
NULL);
|
||||
bfree(filename);
|
||||
filename = find_libobs_data_file("solid.effect");
|
||||
video->solid_effect = gs_create_effect_from_file(filename,
|
||||
NULL);
|
||||
bfree(filename);
|
||||
|
||||
filename = find_libobs_data_file("format_conversion.effect");
|
||||
video->conversion_effect = gs_create_effect_from_file(filename,
|
||||
NULL);
|
||||
bfree(filename);
|
||||
filename = find_libobs_data_file("format_conversion.effect");
|
||||
video->conversion_effect = gs_create_effect_from_file(filename,
|
||||
NULL);
|
||||
bfree(filename);
|
||||
|
||||
if (!video->default_effect)
|
||||
success = false;
|
||||
if (!video->solid_effect)
|
||||
success = false;
|
||||
if (!video->conversion_effect)
|
||||
success = false;
|
||||
}
|
||||
if (!video->default_effect)
|
||||
success = false;
|
||||
if (!video->solid_effect)
|
||||
success = false;
|
||||
if (!video->conversion_effect)
|
||||
success = false;
|
||||
|
||||
gs_leavecontext();
|
||||
return success;
|
||||
return success ? OBS_VIDEO_SUCCESS : OBS_VIDEO_FAIL;
|
||||
}
|
||||
|
||||
static bool obs_init_video(struct obs_video_info *ovi)
|
||||
static int obs_init_video(struct obs_video_info *ovi)
|
||||
{
|
||||
struct obs_core_video *video = &obs->video;
|
||||
struct video_output_info vi;
|
||||
@ -256,16 +258,17 @@ static bool obs_init_video(struct obs_video_info *ovi)
|
||||
errorcode = video_output_open(&video->video, &vi);
|
||||
|
||||
if (errorcode != VIDEO_OUTPUT_SUCCESS) {
|
||||
if (errorcode == VIDEO_OUTPUT_INVALIDPARAM)
|
||||
if (errorcode == VIDEO_OUTPUT_INVALIDPARAM) {
|
||||
blog(LOG_ERROR, "Invalid video parameters specified");
|
||||
else
|
||||
return OBS_VIDEO_INVALID_PARAM;
|
||||
} else {
|
||||
blog(LOG_ERROR, "Could not open video output");
|
||||
|
||||
return false;
|
||||
}
|
||||
return OBS_VIDEO_FAIL;
|
||||
}
|
||||
|
||||
if (!obs_display_init(&video->main_display, NULL))
|
||||
return false;
|
||||
return OBS_VIDEO_FAIL;
|
||||
|
||||
video->main_display.cx = ovi->window_width;
|
||||
video->main_display.cy = ovi->window_height;
|
||||
@ -273,19 +276,19 @@ static bool obs_init_video(struct obs_video_info *ovi)
|
||||
gs_entercontext(video->graphics);
|
||||
|
||||
if (ovi->gpu_conversion && !obs_init_gpu_conversion(ovi))
|
||||
return false;
|
||||
return OBS_VIDEO_FAIL;
|
||||
if (!obs_init_textures(ovi))
|
||||
return false;
|
||||
return OBS_VIDEO_FAIL;
|
||||
|
||||
gs_leavecontext();
|
||||
|
||||
errorcode = pthread_create(&video->video_thread, NULL,
|
||||
obs_video_thread, obs);
|
||||
if (errorcode != 0)
|
||||
return false;
|
||||
return OBS_VIDEO_FAIL;
|
||||
|
||||
video->thread_initialized = true;
|
||||
return true;
|
||||
return OBS_VIDEO_SUCCESS;
|
||||
}
|
||||
|
||||
static void stop_video(void)
|
||||
@ -597,13 +600,26 @@ const char *obs_get_locale(void)
|
||||
return obs ? obs->locale : NULL;
|
||||
}
|
||||
|
||||
bool obs_reset_video(struct obs_video_info *ovi)
|
||||
#define OBS_SIZE_MIN 2
|
||||
#define OBS_SIZE_MAX (32 * 1024)
|
||||
|
||||
static inline bool size_valid(uint32_t width, uint32_t height)
|
||||
{
|
||||
if (!obs) return false;
|
||||
return (width >= OBS_SIZE_MIN && height >= OBS_SIZE_MIN &&
|
||||
width <= OBS_SIZE_MAX && height <= OBS_SIZE_MAX);
|
||||
}
|
||||
|
||||
int obs_reset_video(struct obs_video_info *ovi)
|
||||
{
|
||||
if (!obs) return OBS_VIDEO_FAIL;
|
||||
|
||||
/* don't allow changing of video settings if active. */
|
||||
if (obs->video.video && video_output_active(obs->video.video))
|
||||
return false;
|
||||
return OBS_VIDEO_CURRENTLY_ACTIVE;
|
||||
|
||||
if (!size_valid(ovi->output_width, ovi->output_height) ||
|
||||
!size_valid(ovi->base_width, ovi->base_height))
|
||||
return OBS_VIDEO_INVALID_PARAM;
|
||||
|
||||
struct obs_core_video *video = &obs->video;
|
||||
|
||||
@ -612,15 +628,18 @@ bool obs_reset_video(struct obs_video_info *ovi)
|
||||
|
||||
if (!ovi) {
|
||||
obs_free_graphics();
|
||||
return true;
|
||||
return OBS_VIDEO_SUCCESS;
|
||||
}
|
||||
|
||||
/* align to multiple-of-two and SSE alignment sizes */
|
||||
ovi->output_width &= 0xFFFFFFFC;
|
||||
ovi->output_height &= 0xFFFFFFFE;
|
||||
|
||||
if (!video->graphics && !obs_init_graphics(ovi))
|
||||
return false;
|
||||
if (!video->graphics) {
|
||||
int errorcode = obs_init_graphics(ovi);
|
||||
if (errorcode != OBS_VIDEO_SUCCESS)
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
blog(LOG_INFO, "video settings reset:\n"
|
||||
"\tbase resolution: %dx%d\n"
|
||||
|
17
libobs/obs.h
17
libobs/obs.h
@ -223,11 +223,22 @@ EXPORT void obs_set_locale(const char *locale);
|
||||
EXPORT const char *obs_get_locale(void);
|
||||
|
||||
/**
|
||||
* Sets base video ouput base resolution/fps/format
|
||||
* Sets base video ouput base resolution/fps/format.
|
||||
*
|
||||
* @note Cannot set base video if an output is currently active.
|
||||
* @note This data cannot be changed if an output is corrently active.
|
||||
* @note The graphics module cannot be changed without fully destroying the
|
||||
* OBS context.
|
||||
*
|
||||
* @param ovi Pointer to an obs_video_info structure containing the
|
||||
* specification of the graphics subsystem,
|
||||
* @return OBS_VIDEO_SUCCESS if sucessful
|
||||
* OBS_VIDEO_NOT_SUPPORTED if the adapter lacks capabilities
|
||||
* OBS_VIDEO_INVALID_PARAM if a parameter is invalid
|
||||
* OBS_VIDEO_CURRENTLY_ACTIVE if video is currently active
|
||||
* OBS_VIDEO_MODULE_NOT_FOUND if the graphics module is not found
|
||||
* OBS_VIDEO_FAIL for generic failure
|
||||
*/
|
||||
EXPORT bool obs_reset_video(struct obs_video_info *ovi);
|
||||
EXPORT int obs_reset_video(struct obs_video_info *ovi);
|
||||
|
||||
/**
|
||||
* Sets base audio output format/channels/samples/etc
|
||||
|
@ -513,11 +513,25 @@ void OBSBasic::OBSInit()
|
||||
throw "Failed to initialize libobs";
|
||||
if (!InitBasicConfig())
|
||||
throw "Failed to load basic.ini";
|
||||
if (!ResetVideo())
|
||||
throw "Failed to initialize video";
|
||||
if (!ResetAudio())
|
||||
throw "Failed to initialize audio";
|
||||
|
||||
int ret = ResetVideo();
|
||||
|
||||
switch (ret) {
|
||||
case OBS_VIDEO_MODULE_NOT_FOUND:
|
||||
throw "Failed to initialize video: Graphics module not found";
|
||||
case OBS_VIDEO_NOT_SUPPORTED:
|
||||
throw "Failed to initialize video: Your graphics adapter "
|
||||
"is either too old or does not have the required "
|
||||
"capabilities required for this program";
|
||||
case OBS_VIDEO_INVALID_PARAM:
|
||||
throw "Failed to initialize video: Invalid parameters";
|
||||
default:
|
||||
if (ret != OBS_VIDEO_SUCCESS)
|
||||
throw "Failed to initialize video: Unspecified error";
|
||||
}
|
||||
|
||||
InitOBSCallbacks();
|
||||
|
||||
/* TODO: this is a test, all modules will be searched for and loaded
|
||||
@ -1182,9 +1196,10 @@ void OBSBasic::SetService(obs_service_t newService)
|
||||
}
|
||||
}
|
||||
|
||||
bool OBSBasic::ResetVideo()
|
||||
int OBSBasic::ResetVideo()
|
||||
{
|
||||
struct obs_video_info ovi;
|
||||
int ret;
|
||||
|
||||
GetConfigFPS(ovi.fps_num, ovi.fps_den);
|
||||
|
||||
@ -1210,11 +1225,11 @@ bool OBSBasic::ResetVideo()
|
||||
ovi.window_width = size.width();
|
||||
ovi.window_height = size.height();
|
||||
|
||||
if (!obs_reset_video(&ovi))
|
||||
return false;
|
||||
ret = obs_reset_video(&ovi);
|
||||
if (ret == OBS_VIDEO_SUCCESS)
|
||||
obs_add_draw_callback(OBSBasic::RenderMain, this);
|
||||
|
||||
obs_add_draw_callback(OBSBasic::RenderMain, this);
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool OBSBasic::ResetAudio()
|
||||
|
@ -191,7 +191,7 @@ public:
|
||||
obs_service_t GetService();
|
||||
void SetService(obs_service_t service);
|
||||
|
||||
bool ResetVideo();
|
||||
int ResetVideo();
|
||||
bool ResetAudio();
|
||||
|
||||
void ResetAudioDevice(const char *sourceId, const char *deviceName,
|
||||
|
@ -55,7 +55,7 @@ static void CreateOBS(NSView *view)
|
||||
ovi.window_height = cy;
|
||||
ovi.window.view = view;
|
||||
|
||||
if (!obs_reset_video(&ovi))
|
||||
if (obs_reset_video(&ovi) != 0)
|
||||
throw "Couldn't initialize video";
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ static void CreateOBS(HWND hwnd)
|
||||
ovi.output_height = rc.bottom;
|
||||
ovi.window.hwnd = hwnd;
|
||||
|
||||
if (!obs_reset_video(&ovi))
|
||||
if (obs_reset_video(&ovi) != 0)
|
||||
throw "Couldn't initialize video";
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user