(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.
master
jp9000 2014-07-20 17:40:57 -07:00
parent e62f965d3e
commit 778cc2b318
13 changed files with 150 additions and 72 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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()

View File

@ -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,

View File

@ -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";
}

View File

@ -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";
}