New upstream version 25.0.8+dfsg1
This commit is contained in:
parent
8b2e5f2130
commit
8e020cdacb
115 changed files with 1767 additions and 10949 deletions
|
|
@ -46,6 +46,7 @@ elseif("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD")
|
|||
add_subdirectory(linux-pulseaudio)
|
||||
add_subdirectory(linux-v4l2)
|
||||
add_subdirectory(linux-jack)
|
||||
add_subdirectory(linux-alsa)
|
||||
endif()
|
||||
|
||||
option(BUILD_BROWSER "Build browser plugin" OFF)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ set(coreaudio-encoder_SOURCES
|
|||
encoder.cpp)
|
||||
|
||||
if (WIN32)
|
||||
set(MODULE_DESCRIPTION "OBS Core Audio encoder")
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in coreaudio-encoder.rc)
|
||||
list(APPEND coreaudio-encoder_SOURCES
|
||||
coreaudio-encoder.rc)
|
||||
set(coreaudio-encoder_HEADERS windows-imports.h)
|
||||
set(coreaudio-encoder_LIBS )
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,9 @@ static bool decklink_output_start(void *data)
|
|||
|
||||
device.Set(deviceEnum->FindByHash(decklink->deviceHash));
|
||||
|
||||
if (!device)
|
||||
return false;
|
||||
|
||||
DeckLinkDeviceMode *mode = device->FindOutputMode(decklink->modeID);
|
||||
|
||||
decklink->SetSize(mode->GetWidth(), mode->GetHeight());
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ set(win-decklink_HEADERS
|
|||
../util.hpp
|
||||
)
|
||||
|
||||
set(MODULE_DESCRIPTION "OBS DeckLink Windows module")
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in win-decklink.rc)
|
||||
set(win-decklink_SOURCES
|
||||
../plugin-main.cpp
|
||||
../decklink-devices.cpp
|
||||
|
|
@ -46,7 +48,7 @@ set(win-decklink_SOURCES
|
|||
../audio-repack.c
|
||||
platform.cpp
|
||||
../util.cpp
|
||||
)
|
||||
win-decklink.rc)
|
||||
|
||||
add_idl_files(win-decklink-sdk_GENERATED_FILES
|
||||
${win-decklink-sdk_IDLS}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,13 @@ set(image-source_SOURCES
|
|||
color-source.c
|
||||
obs-slideshow.c)
|
||||
|
||||
if(WIN32)
|
||||
set(MODULE_DESCRIPTION "OBS image module")
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in image-source.rc)
|
||||
list(APPEND image-source_SOURCES
|
||||
image-source.rc)
|
||||
endif()
|
||||
|
||||
add_library(image-source MODULE
|
||||
${image-source_SOURCES})
|
||||
target_link_libraries(image-source
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ static enum speaker_layout jack_channels_to_obs_speakers(uint_fast32_t channels)
|
|||
return SPEAKERS_STEREO;
|
||||
case 3:
|
||||
return SPEAKERS_2POINT1;
|
||||
case 4:
|
||||
return SPEAKERS_4POINT0;
|
||||
case 5:
|
||||
return SPEAKERS_4POINT1;
|
||||
case 6:
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ static inline bool valid_control(struct v4l2_queryctrl *qctrl)
|
|||
return (qctrl->flags & INVALID_CONTROL_FLAGS) == 0;
|
||||
}
|
||||
|
||||
static inline bool add_control_property(obs_properties_t *props,
|
||||
static inline void add_control_property(obs_properties_t *props,
|
||||
obs_data_t *settings, int_fast32_t dev,
|
||||
struct v4l2_queryctrl *qctrl)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
struct cocoa_window {
|
||||
CGWindowID window_id;
|
||||
int owner_pid;
|
||||
|
||||
pthread_mutex_t name_lock;
|
||||
NSString *owner_name;
|
||||
|
|
|
|||
|
|
@ -60,8 +60,11 @@ bool find_window(cocoa_window_t cw, obs_data_t *settings, bool force)
|
|||
|
||||
NSNumber *window_id = (NSNumber *)dict[WINDOW_NUMBER];
|
||||
cw->window_id = window_id.intValue;
|
||||
NSNumber *owner_pid = (NSNumber *)dict[OWNER_PID];
|
||||
cw->owner_pid = owner_pid.intValue;
|
||||
|
||||
obs_data_set_int(settings, "window", cw->window_id);
|
||||
obs_data_set_int(settings, "owner_pid", cw->owner_pid);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -78,7 +81,41 @@ void init_window(cocoa_window_t cw, obs_data_t *settings)
|
|||
cw->window_name = @(obs_data_get_string(settings, "window_name"));
|
||||
[cw->owner_name retain];
|
||||
[cw->window_name retain];
|
||||
find_window(cw, settings, true);
|
||||
|
||||
// Find initial window.
|
||||
pthread_mutex_lock(&cw->name_lock);
|
||||
|
||||
if (!cw->window_name.length && !cw->owner_name.length)
|
||||
goto invalid_name;
|
||||
|
||||
NSNumber *owner_pid = @(obs_data_get_int(settings, "owner_pid"));
|
||||
NSNumber *window_id = @(obs_data_get_int(settings, "window"));
|
||||
for (NSDictionary *dict in enumerate_windows()) {
|
||||
bool owner_names_match =
|
||||
[cw->owner_name isEqualToString:dict[OWNER_NAME]];
|
||||
bool ids_match =
|
||||
[owner_pid isEqualToNumber:dict[OWNER_PID]] &&
|
||||
[window_id isEqualToNumber:dict[WINDOW_NUMBER]];
|
||||
bool window_names_match =
|
||||
[cw->window_name isEqualToString:dict[WINDOW_NAME]];
|
||||
|
||||
if (owner_names_match && (ids_match || window_names_match)) {
|
||||
pthread_mutex_unlock(&cw->name_lock);
|
||||
|
||||
NSNumber *window_id = (NSNumber *)dict[WINDOW_NUMBER];
|
||||
cw->window_id = window_id.intValue;
|
||||
NSNumber *owner_pid = (NSNumber *)dict[OWNER_PID];
|
||||
cw->owner_pid = owner_pid.intValue;
|
||||
|
||||
obs_data_set_int(settings, "window", cw->window_id);
|
||||
obs_data_set_int(settings, "owner_pid", cw->owner_pid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
invalid_name:
|
||||
pthread_mutex_unlock(&cw->name_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
void destroy_window(cocoa_window_t cw)
|
||||
|
|
@ -99,6 +136,7 @@ void update_window(cocoa_window_t cw, obs_data_t *settings)
|
|||
[cw->window_name retain];
|
||||
pthread_mutex_unlock(&cw->name_lock);
|
||||
|
||||
cw->owner_pid = obs_data_get_int(settings, "owner_pid");
|
||||
cw->window_id = obs_data_get_int(settings, "window");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@ set(syphon_SOURCES
|
|||
syphon-framework/SyphonServerDirectory.m
|
||||
)
|
||||
|
||||
add_library(syphon-framework ${syphon_HEADERS}
|
||||
${syphon_SOURCES})
|
||||
|
||||
set(mac-syphon_HEADERS
|
||||
)
|
||||
|
||||
|
|
@ -70,15 +73,17 @@ add_definitions(-DSYPHON_UNIQUE_CLASS_NAME_PREFIX=OBS_ -include
|
|||
|
||||
add_library(mac-syphon MODULE
|
||||
${mac-syphon_SOURCES}
|
||||
${mac-syphon_HEADERS}
|
||||
${syphon_HEADERS}
|
||||
${syphon_SOURCES})
|
||||
${mac-syphon_HEADERS})
|
||||
|
||||
target_link_libraries(mac-syphon
|
||||
libobs
|
||||
syphon-framework
|
||||
${COCOA}
|
||||
${IOSURF}
|
||||
${SCRIPTINGBRIDGE}
|
||||
${OPENGL_gl_LIBRARY})
|
||||
|
||||
set_property (TARGET mac-syphon APPEND_STRING PROPERTY
|
||||
COMPILE_FLAGS "-fobjc-arc")
|
||||
|
||||
install_obs_plugin_with_data(mac-syphon data)
|
||||
|
|
|
|||
|
|
@ -41,12 +41,6 @@ struct syphon {
|
|||
};
|
||||
typedef struct syphon *syphon_t;
|
||||
|
||||
static inline void objc_release(NSObject **obj)
|
||||
{
|
||||
[*obj release];
|
||||
*obj = nil;
|
||||
}
|
||||
|
||||
static inline void update_properties(syphon_t s)
|
||||
{
|
||||
obs_source_update_properties(s->source);
|
||||
|
|
@ -101,10 +95,7 @@ static void stop_client(syphon_t s)
|
|||
obs_enter_graphics();
|
||||
|
||||
if (s->client) {
|
||||
@autoreleasepool {
|
||||
[s->client stop];
|
||||
objc_release(&s->client);
|
||||
}
|
||||
[s->client stop];
|
||||
}
|
||||
|
||||
if (s->tex) {
|
||||
|
|
@ -178,16 +169,6 @@ static inline void check_description(syphon_t s, NSDictionary *desc)
|
|||
surfaces_string.UTF8String);
|
||||
}
|
||||
|
||||
static inline bool update_string(NSString **str, NSString *new)
|
||||
{
|
||||
if (!new)
|
||||
return false;
|
||||
|
||||
[*str release];
|
||||
*str = [new retain];
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void handle_new_frame(syphon_t s,
|
||||
SYPHON_CLIENT_UNIQUE_CLASS_NAME *client)
|
||||
{
|
||||
|
|
@ -233,35 +214,26 @@ static void create_client(syphon_t s)
|
|||
NSDictionary *desc = find_by_uuid(servers, s->uuid);
|
||||
if (!desc) {
|
||||
desc = servers[0];
|
||||
if (update_string(&s->uuid,
|
||||
desc[SyphonServerDescriptionUUIDKey]))
|
||||
if (![s->uuid isEqualToString:
|
||||
desc[SyphonServerDescriptionUUIDKey]]) {
|
||||
s->uuid_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
check_version(s, desc);
|
||||
check_description(s, desc);
|
||||
|
||||
@autoreleasepool {
|
||||
s->client = [[SYPHON_CLIENT_UNIQUE_CLASS_NAME alloc]
|
||||
initWithServerDescription:desc
|
||||
options:nil
|
||||
newFrameHandler:^(
|
||||
SYPHON_CLIENT_UNIQUE_CLASS_NAME
|
||||
*client) {
|
||||
handle_new_frame(s, client);
|
||||
}];
|
||||
}
|
||||
s->client = [[SYPHON_CLIENT_UNIQUE_CLASS_NAME alloc]
|
||||
initWithServerDescription:desc
|
||||
options:nil
|
||||
newFrameHandler:^(
|
||||
SYPHON_CLIENT_UNIQUE_CLASS_NAME *client) {
|
||||
handle_new_frame(s, client);
|
||||
}];
|
||||
|
||||
s->active = true;
|
||||
}
|
||||
|
||||
static inline void release_settings(syphon_t s)
|
||||
{
|
||||
[s->app_name release];
|
||||
[s->name release];
|
||||
[s->uuid release];
|
||||
}
|
||||
|
||||
static inline bool load_syphon_settings(syphon_t s, obs_data_t *settings)
|
||||
{
|
||||
NSString *app_name = @(obs_data_get_string(settings, "app_name"));
|
||||
|
|
@ -275,10 +247,9 @@ static inline bool load_syphon_settings(syphon_t s, obs_data_t *settings)
|
|||
if ([uuid isEqual:s->uuid] && equal_names)
|
||||
return false;
|
||||
|
||||
release_settings(s);
|
||||
s->app_name = [app_name retain];
|
||||
s->name = [name retain];
|
||||
s->uuid = [uuid retain];
|
||||
s->app_name = app_name;
|
||||
s->name = name;
|
||||
s->uuid = uuid;
|
||||
s->uuid_changed = false;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -299,10 +270,12 @@ static inline void update_from_announce(syphon_t s, NSDictionary *info)
|
|||
!([app_name isEqual:s->app_name] && [name isEqual:s->name]))
|
||||
return;
|
||||
|
||||
update_string(&s->app_name, app_name);
|
||||
update_string(&s->name, name);
|
||||
if (update_string(&s->uuid, uuid))
|
||||
s->app_name = app_name;
|
||||
s->name = name;
|
||||
if (![s->uuid isEqualToString:uuid]) {
|
||||
s->uuid = uuid;
|
||||
s->uuid_changed = true;
|
||||
}
|
||||
|
||||
create_client(s);
|
||||
}
|
||||
|
|
@ -324,8 +297,6 @@ static inline void update_inject_state(syphon_t s, NSDictionary *info,
|
|||
|
||||
if (!(s->inject_server_found = announce)) {
|
||||
s->inject_wait_time = 0.f;
|
||||
|
||||
objc_release(&s->inject_uuid);
|
||||
LOG(LOG_INFO,
|
||||
"Injected server retired: "
|
||||
"[%s] InjectedSyphon (%s)",
|
||||
|
|
@ -336,7 +307,7 @@ static inline void update_inject_state(syphon_t s, NSDictionary *info,
|
|||
if (s->inject_uuid) //TODO: track multiple injected instances?
|
||||
return;
|
||||
|
||||
s->inject_uuid = [uuid retain];
|
||||
s->inject_uuid = uuid;
|
||||
LOG(LOG_INFO, "Injected server found: [%s] %s (%s)",
|
||||
app_name.UTF8String, name.UTF8String, uuid.UTF8String);
|
||||
}
|
||||
|
|
@ -487,26 +458,31 @@ static void *syphon_create_internal(obs_data_t *settings, obs_source_t *source)
|
|||
|
||||
s->source = source;
|
||||
|
||||
if (!init_obs_graphics_objects(s))
|
||||
goto fail;
|
||||
if (!init_obs_graphics_objects(s)) {
|
||||
syphon_destroy_internal(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!load_syphon_settings(s, settings))
|
||||
goto fail;
|
||||
if (!load_syphon_settings(s, settings)) {
|
||||
syphon_destroy_internal(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *inject_info = obs_data_get_string(settings, "application");
|
||||
s->inject_info = obs_data_create_from_json(inject_info);
|
||||
s->inject_active = obs_data_get_bool(settings, "inject");
|
||||
s->inject_app = @(obs_data_get_string(s->inject_info, "name"));
|
||||
|
||||
if (s->inject_app)
|
||||
[s->inject_app retain];
|
||||
|
||||
if (!create_syphon_listeners(s))
|
||||
goto fail;
|
||||
if (!create_syphon_listeners(s)) {
|
||||
syphon_destroy_internal(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
|
||||
if (!create_applications_observer(s, ws))
|
||||
goto fail;
|
||||
if (!create_applications_observer(s, ws)) {
|
||||
syphon_destroy_internal(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (s->inject_active)
|
||||
find_and_inject_target(s, ws.runningApplications, false);
|
||||
|
|
@ -519,10 +495,6 @@ static void *syphon_create_internal(obs_data_t *settings, obs_source_t *source)
|
|||
obs_data_get_bool(settings, "allow_transparency");
|
||||
|
||||
return s;
|
||||
|
||||
fail:
|
||||
syphon_destroy_internal(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *syphon_create(obs_data_t *settings, obs_source_t *source)
|
||||
|
|
@ -550,15 +522,9 @@ static inline void syphon_destroy_internal(syphon_t s)
|
|||
[ws removeObserver:s->launch_listener
|
||||
forKeyPath:NSStringFromSelector(@selector
|
||||
(runningApplications))];
|
||||
objc_release(&s->launch_listener);
|
||||
|
||||
objc_release(&s->inject_app);
|
||||
objc_release(&s->inject_uuid);
|
||||
|
||||
obs_data_release(s->inject_info);
|
||||
|
||||
release_settings(s);
|
||||
|
||||
obs_enter_graphics();
|
||||
stop_client(s);
|
||||
|
||||
|
|
@ -1198,11 +1164,7 @@ static inline void update_inject(syphon_t s, obs_data_t *settings)
|
|||
obs_data_t *prev = s->inject_info;
|
||||
s->inject_info = obs_data_create_from_json(inject_str);
|
||||
|
||||
NSString *prev_app = s->inject_app;
|
||||
s->inject_app = [@(obs_data_get_string(s->inject_info, "name")) retain];
|
||||
[prev_app release];
|
||||
|
||||
objc_release(&s->inject_uuid);
|
||||
s->inject_app = @(obs_data_get_string(s->inject_info, "name"));
|
||||
|
||||
SyphonServerDirectory *ssd = [SyphonServerDirectory sharedDirectory];
|
||||
NSArray *servers = [ssd serversMatchingName:@"InjectedSyphon"
|
||||
|
|
|
|||
|
|
@ -46,9 +46,12 @@ if(ENABLE_FFMPEG_LOGGING)
|
|||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(MODULE_DESCRIPTION "OBS FFmpeg module")
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in obs-ffmpeg.rc)
|
||||
list(APPEND obs-ffmpeg_SOURCES
|
||||
jim-nvenc.c
|
||||
jim-nvenc-helpers.c)
|
||||
jim-nvenc-helpers.c
|
||||
obs-ffmpeg.rc)
|
||||
list(APPEND obs-ffmpeg_HEADERS
|
||||
jim-nvenc.h)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -58,3 +58,11 @@ ReplayBuffer.Save="Save Replay"
|
|||
HelperProcessFailed="Unable to start the recording helper process. Check that OBS files have not been blocked or removed by any 3rd party antivirus / security software."
|
||||
UnableToWritePath="Unable to write to %1. Make sure you're using a recording path which your user account is allowed to write to and that there is sufficient disk space."
|
||||
WarnWindowsDefender="If Windows 10 Ransomware Protection is enabled it can also cause this error. Try turning off controlled folder access in Windows Security / Virus & threat protection settings."
|
||||
|
||||
NVENC.Error="Failed to open NVENC codec: %1"
|
||||
NVENC.GenericError="Check your video drivers are up to date. Try closing other recording software which might be using NVENC such as NVIDIA Shadowplay or Windows 10 Game DVR."
|
||||
NVENC.BadGPUIndex="You have selected GPU %1 in your output encoder settings. Set this back to 0 and try again."
|
||||
NVENC.OutdatedDriver="Your current video card driver does not support this NVENC version, please update your drivers."
|
||||
NVENC.UnsupportedDevice="NVENC Error: Unsupported device. Check your video card supports NVENC and that the drivers are up to date."
|
||||
NVENC.TooManySessions="NVENC Error: Too many concurrent sessions. Try closing other recording software which might be using NVENC such as NVIDIA Shadowplay or Windows 10 Game DVR."
|
||||
NVENC.CheckDrivers="Please check your video drivers are up to date."
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "jim-nvenc.h"
|
||||
#include <util/platform.h>
|
||||
#include <util/threading.h>
|
||||
#include <util/dstr.h>
|
||||
|
||||
static void *nvenc_lib = NULL;
|
||||
static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
|
@ -9,18 +10,40 @@ NV_CREATE_INSTANCE_FUNC nv_create_instance = NULL;
|
|||
|
||||
#define error(format, ...) blog(LOG_ERROR, "[jim-nvenc] " format, ##__VA_ARGS__)
|
||||
|
||||
static inline bool nv_failed(NVENCSTATUS err, const char *func,
|
||||
const char *call)
|
||||
bool nv_failed(obs_encoder_t *encoder, NVENCSTATUS err, const char *func,
|
||||
const char *call)
|
||||
{
|
||||
if (err == NV_ENC_SUCCESS)
|
||||
struct dstr error_message = {0};
|
||||
|
||||
switch (err) {
|
||||
case NV_ENC_SUCCESS:
|
||||
return false;
|
||||
|
||||
case NV_ENC_ERR_OUT_OF_MEMORY:
|
||||
obs_encoder_set_last_error(
|
||||
encoder, obs_module_text("NVENC.TooManySessions"));
|
||||
break;
|
||||
|
||||
case NV_ENC_ERR_UNSUPPORTED_DEVICE:
|
||||
obs_encoder_set_last_error(
|
||||
encoder, obs_module_text("NVENC.UnsupportedDevice"));
|
||||
break;
|
||||
|
||||
default:
|
||||
dstr_printf(&error_message,
|
||||
"NVENC Error: %s: %s failed: %d (%s)", func, call,
|
||||
(int)err, nv_error_name(err));
|
||||
obs_encoder_set_last_error(encoder, error_message.array);
|
||||
dstr_free(&error_message);
|
||||
break;
|
||||
}
|
||||
|
||||
error("%s: %s failed: %d (%s)", func, call, (int)err,
|
||||
nv_error_name(err));
|
||||
return true;
|
||||
}
|
||||
|
||||
#define NV_FAILED(x) nv_failed(x, __FUNCTION__, #x)
|
||||
#define NV_FAILED(e, x) nv_failed(e, x, __FUNCTION__, #x)
|
||||
|
||||
bool load_nvenc_lib(void)
|
||||
{
|
||||
|
|
@ -83,7 +106,7 @@ const char *nv_error_name(NVENCSTATUS err)
|
|||
return "Unknown Error";
|
||||
}
|
||||
|
||||
static inline bool init_nvenc_internal(void)
|
||||
static inline bool init_nvenc_internal(obs_encoder_t *encoder)
|
||||
{
|
||||
static bool initialized = false;
|
||||
static bool success = false;
|
||||
|
|
@ -95,17 +118,24 @@ static inline bool init_nvenc_internal(void)
|
|||
NV_MAX_VER_FUNC nv_max_ver = (NV_MAX_VER_FUNC)load_nv_func(
|
||||
"NvEncodeAPIGetMaxSupportedVersion");
|
||||
if (!nv_max_ver) {
|
||||
obs_encoder_set_last_error(
|
||||
encoder,
|
||||
"Missing NvEncodeAPIGetMaxSupportedVersion, check "
|
||||
"your video card drivers are up to date.");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t ver = 0;
|
||||
if (NV_FAILED(nv_max_ver(&ver))) {
|
||||
if (NV_FAILED(encoder, nv_max_ver(&ver))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t cur_ver = (NVENCAPI_MAJOR_VERSION << 4) |
|
||||
NVENCAPI_MINOR_VERSION;
|
||||
if (cur_ver > ver) {
|
||||
obs_encoder_set_last_error(
|
||||
encoder, obs_module_text("NVENC.OutdatedDriver"));
|
||||
|
||||
error("Current driver version does not support this NVENC "
|
||||
"version, please upgrade your driver");
|
||||
return false;
|
||||
|
|
@ -114,10 +144,13 @@ static inline bool init_nvenc_internal(void)
|
|||
nv_create_instance = (NV_CREATE_INSTANCE_FUNC)load_nv_func(
|
||||
"NvEncodeAPICreateInstance");
|
||||
if (!nv_create_instance) {
|
||||
obs_encoder_set_last_error(
|
||||
encoder, "Missing NvEncodeAPICreateInstance, check "
|
||||
"your video card drivers are up to date.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NV_FAILED(nv_create_instance(&nv))) {
|
||||
if (NV_FAILED(encoder, nv_create_instance(&nv))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -125,12 +158,12 @@ static inline bool init_nvenc_internal(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool init_nvenc(void)
|
||||
bool init_nvenc(obs_encoder_t *encoder)
|
||||
{
|
||||
bool success;
|
||||
|
||||
pthread_mutex_lock(&init_mutex);
|
||||
success = init_nvenc_internal();
|
||||
success = init_nvenc_internal(encoder);
|
||||
pthread_mutex_unlock(&init_mutex);
|
||||
|
||||
return success;
|
||||
|
|
|
|||
|
|
@ -81,18 +81,7 @@ struct nv_bitstream {
|
|||
HANDLE event;
|
||||
};
|
||||
|
||||
static inline bool nv_failed(struct nvenc_data *enc, NVENCSTATUS err,
|
||||
const char *func, const char *call)
|
||||
{
|
||||
if (err == NV_ENC_SUCCESS)
|
||||
return false;
|
||||
|
||||
error("%s: %s failed: %d (%s)", func, call, (int)err,
|
||||
nv_error_name(err));
|
||||
return true;
|
||||
}
|
||||
|
||||
#define NV_FAILED(x) nv_failed(enc, x, __FUNCTION__, #x)
|
||||
#define NV_FAILED(x) nv_failed(enc->encoder, x, __FUNCTION__, #x)
|
||||
|
||||
static bool nv_bitstream_init(struct nvenc_data *enc, struct nv_bitstream *bs)
|
||||
{
|
||||
|
|
@ -400,7 +389,8 @@ static bool init_encoder(struct nvenc_data *enc, obs_data_t *settings)
|
|||
err = nv.nvEncGetEncodePresetConfig(enc->session,
|
||||
NV_ENC_CODEC_H264_GUID, nv_preset,
|
||||
&preset_config);
|
||||
if (nv_failed(enc, err, __FUNCTION__, "nvEncGetEncodePresetConfig")) {
|
||||
if (nv_failed(enc->encoder, err, __FUNCTION__,
|
||||
"nvEncGetEncodePresetConfig")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -578,16 +568,19 @@ static void *nvenc_create(obs_data_t *settings, obs_encoder_t *encoder)
|
|||
* gpu other than the one OBS is currently running on. */
|
||||
int gpu = (int)obs_data_get_int(settings, "gpu");
|
||||
if (gpu != 0) {
|
||||
info("different GPU selected by user, falling back to ffmpeg");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (obs_encoder_scaling_enabled(encoder)) {
|
||||
info("scaling enabled, falling back to ffmpeg");
|
||||
goto fail;
|
||||
}
|
||||
if (!obs_nv12_tex_active()) {
|
||||
info("nv12 not active, falling back to ffmpeg");
|
||||
goto fail;
|
||||
}
|
||||
if (!init_nvenc()) {
|
||||
if (!init_nvenc(encoder)) {
|
||||
goto fail;
|
||||
}
|
||||
if (NV_FAILED(nv_create_instance(&init))) {
|
||||
|
|
@ -766,7 +759,8 @@ static bool get_encoded_packet(struct nvenc_data *enc, bool finalize)
|
|||
if (nvtex->mapped_res) {
|
||||
NVENCSTATUS err;
|
||||
err = nv.nvEncUnmapInputResource(s, nvtex->mapped_res);
|
||||
if (nv_failed(enc, err, __FUNCTION__, "unmap")) {
|
||||
if (nv_failed(enc->encoder, err, __FUNCTION__,
|
||||
"unmap")) {
|
||||
return false;
|
||||
}
|
||||
nvtex->mapped_res = NULL;
|
||||
|
|
@ -859,7 +853,8 @@ static bool nvenc_encode_tex(void *data, uint32_t handle, int64_t pts,
|
|||
|
||||
err = nv.nvEncEncodePicture(enc->session, ¶ms);
|
||||
if (err != NV_ENC_SUCCESS && err != NV_ENC_ERR_NEED_MORE_INPUT) {
|
||||
nv_failed(enc, err, __FUNCTION__, "nvEncEncodePicture");
|
||||
nv_failed(enc->encoder, err, __FUNCTION__,
|
||||
"nvEncEncodePicture");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,4 +12,6 @@ typedef NVENCSTATUS(NVENCAPI *NV_CREATE_INSTANCE_FUNC)(
|
|||
extern const char *nv_error_name(NVENCSTATUS err);
|
||||
extern NV_ENCODE_API_FUNCTION_LIST nv;
|
||||
extern NV_CREATE_INSTANCE_FUNC nv_create_instance;
|
||||
extern bool init_nvenc(void);
|
||||
extern bool init_nvenc(obs_encoder_t *encoder);
|
||||
bool nv_failed(obs_encoder_t *encoder, NVENCSTATUS err, const char *func,
|
||||
const char *call);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include <util/base.h>
|
||||
#include <util/circlebuf.h>
|
||||
#include <util/darray.h>
|
||||
#include <util/dstr.h>
|
||||
#include <obs-module.h>
|
||||
|
||||
#include <libavutil/opt.h>
|
||||
|
|
@ -143,6 +144,11 @@ static bool initialize_codec(struct enc_encoder *enc)
|
|||
|
||||
ret = avcodec_open2(enc->context, enc->codec, NULL);
|
||||
if (ret < 0) {
|
||||
struct dstr error_message = {0};
|
||||
dstr_printf(&error_message, "Failed to open AAC codec: %s",
|
||||
av_err2str(ret));
|
||||
obs_encoder_set_last_error(enc->encoder, error_message.array);
|
||||
dstr_free(&error_message);
|
||||
warn("Failed to open AAC codec: %s", av_err2str(ret));
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,8 +88,50 @@ static bool nvenc_init_codec(struct nvenc_encoder *enc)
|
|||
{
|
||||
int ret;
|
||||
|
||||
// avcodec_open2 will overwrite priv_data, we call this to get a
|
||||
// local copy of the "gpu" setting for improved error messages.
|
||||
int64_t gpu;
|
||||
if (av_opt_get_int(enc->context->priv_data, "gpu", 0, &gpu) < 0) {
|
||||
gpu = -1;
|
||||
}
|
||||
|
||||
ret = avcodec_open2(enc->context, enc->nvenc, NULL);
|
||||
if (ret < 0) {
|
||||
// if we were a fallback from jim-nvenc, there may already be a
|
||||
// more useful error returned from that, so don't overwrite.
|
||||
// this can be removed if / when ffmpeg fallback is removed.
|
||||
if (!obs_encoder_get_last_error(enc->encoder)) {
|
||||
struct dstr error_message = {0};
|
||||
|
||||
dstr_copy(&error_message,
|
||||
obs_module_text("NVENC.Error"));
|
||||
dstr_replace(&error_message, "%1", av_err2str(ret));
|
||||
dstr_cat(&error_message, "\r\n\r\n");
|
||||
|
||||
if (gpu > 0) {
|
||||
// if a non-zero GPU failed, almost always
|
||||
// user error. tell then to fix it.
|
||||
char gpu_str[16];
|
||||
snprintf(gpu_str, sizeof(gpu_str) - 1, "%d",
|
||||
(int)gpu);
|
||||
gpu_str[sizeof(gpu_str) - 1] = 0;
|
||||
|
||||
dstr_cat(&error_message,
|
||||
obs_module_text("NVENC.BadGPUIndex"));
|
||||
dstr_replace(&error_message, "%1", gpu_str);
|
||||
} else if (ret == AVERROR_EXTERNAL) {
|
||||
// special case for common NVENC error
|
||||
dstr_cat(&error_message,
|
||||
obs_module_text("NVENC.GenericError"));
|
||||
} else {
|
||||
dstr_cat(&error_message,
|
||||
obs_module_text("NVENC.CheckDrivers"));
|
||||
}
|
||||
|
||||
obs_encoder_set_last_error(enc->encoder,
|
||||
error_message.array);
|
||||
dstr_free(&error_message);
|
||||
}
|
||||
warn("Failed to open NVENC codec: %s", av_err2str(ret));
|
||||
return false;
|
||||
}
|
||||
|
|
@ -296,6 +338,8 @@ static void *nvenc_create(obs_data_t *settings, obs_encoder_t *encoder)
|
|||
blog(LOG_INFO, "---------------------------------");
|
||||
|
||||
if (!enc->nvenc) {
|
||||
obs_encoder_set_last_error(encoder,
|
||||
"Couldn't find NVENC encoder");
|
||||
warn("Couldn't find encoder");
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -258,10 +258,11 @@ static void media_stopped(void *opaque)
|
|||
struct ffmpeg_source *s = opaque;
|
||||
if (s->is_clear_on_media_end) {
|
||||
obs_source_output_video(s->source, NULL);
|
||||
if (s->close_when_inactive && s->media_valid)
|
||||
s->destroy_media = true;
|
||||
}
|
||||
|
||||
if (s->close_when_inactive && s->media_valid)
|
||||
s->destroy_media = true;
|
||||
|
||||
set_media_state(s, OBS_MEDIA_STATE_ENDED);
|
||||
obs_source_media_ended(s->source);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -240,6 +240,11 @@ bool obs_module_load(void)
|
|||
#ifdef _WIN32
|
||||
if (get_win_ver_int() > 0x0601) {
|
||||
jim_nvenc_load();
|
||||
} else {
|
||||
// if on Win 7, new nvenc isn't available so there's
|
||||
// no nvenc encoder for the user to select, expose
|
||||
// the old encoder directly
|
||||
nvenc_encoder_info.caps &= ~OBS_ENCODER_CAP_INTERNAL;
|
||||
}
|
||||
#endif
|
||||
obs_register_encoder(&nvenc_encoder_info);
|
||||
|
|
|
|||
|
|
@ -54,6 +54,13 @@ set(obs-filters_SOURCES
|
|||
expander-filter.c
|
||||
luma-key-filter.c)
|
||||
|
||||
if(WIN32)
|
||||
set(MODULE_DESCRIPTION "OBS A/V Filters")
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in obs-filters.rc)
|
||||
list(APPEND obs-filters_SOURCES
|
||||
obs-filters.rc)
|
||||
endif()
|
||||
|
||||
add_library(obs-filters MODULE
|
||||
${obs-filters_SOURCES}
|
||||
${obs-filters_config_HEADERS}
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ static obs_properties_t *color_grade_filter_properties(void *data)
|
|||
obs_properties_t *props = obs_properties_create();
|
||||
struct dstr filter_str = {0};
|
||||
|
||||
dstr_cat(&filter_str, "(*.cube *.png)");
|
||||
dstr_cat(&filter_str, "PNG/Cube (*.cube *.png)");
|
||||
|
||||
if (s && s->file && *s->file) {
|
||||
dstr_copy(&path, s->file);
|
||||
|
|
|
|||
|
|
@ -156,6 +156,13 @@ set(obs-outputs_SOURCES
|
|||
flv-mux.c
|
||||
net-if.c)
|
||||
|
||||
if(WIN32)
|
||||
set(MODULE_DESCRIPTION "OBS output module")
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in obs-outputs.rc)
|
||||
list(APPEND obs-outputs_SOURCES
|
||||
obs-outputs.rc)
|
||||
endif()
|
||||
|
||||
add_library(obs-outputs MODULE
|
||||
${ftl_SOURCES}
|
||||
${ftl_HEADERS}
|
||||
|
|
|
|||
|
|
@ -360,6 +360,8 @@ error:
|
|||
mbedtls_x509_crt_free(chain);
|
||||
free(chain);
|
||||
r->RTMP_TLS_ctx->cacert = NULL;
|
||||
#else /* USE_MBEDTLS */
|
||||
UNUSED_PARAMETER(r);
|
||||
#endif /* USE_MBEDTLS */
|
||||
}
|
||||
|
||||
|
|
@ -407,6 +409,7 @@ RTMP_TLS_Init(RTMP *r)
|
|||
SSL_CTX_set_default_verify_paths(RTMP_TLS_ctx);
|
||||
#endif
|
||||
#else
|
||||
UNUSED_PARAMETER(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -429,6 +432,8 @@ RTMP_TLS_Free(RTMP *r) {
|
|||
// NO mbedtls_net_free() BECAUSE WE SET IT UP BY HAND!
|
||||
free(r->RTMP_TLS_ctx);
|
||||
r->RTMP_TLS_ctx = NULL;
|
||||
#else
|
||||
UNUSED_PARAMETER(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,11 @@ endif()
|
|||
project(obs-text)
|
||||
|
||||
if(WIN32)
|
||||
set(MODULE_DESCRIPTION "OBS GDI+ text module")
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in obs-text.rc)
|
||||
set(obs-text_PLATFORM_SOURCES
|
||||
gdiplus/obs-text.cpp)
|
||||
gdiplus/obs-text.cpp
|
||||
obs-text.rc)
|
||||
set(obs-text_PLATFORM_DEPS
|
||||
gdiplus)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -11,6 +11,13 @@ set(obs-transitions_SOURCES
|
|||
transition-stinger.c
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(MODULE_DESCRIPTION "OBS Transitions module")
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in obs-transitions.rc)
|
||||
list(APPEND obs-transitions_SOURCES
|
||||
obs-transitions.rc)
|
||||
endif()
|
||||
|
||||
add_library(obs-transitions MODULE
|
||||
${obs-transitions_SOURCES})
|
||||
target_link_libraries(obs-transitions
|
||||
|
|
|
|||
|
|
@ -8,6 +8,13 @@ set(obs-x264_SOURCES
|
|||
obs-x264.c
|
||||
obs-x264-plugin-main.c)
|
||||
|
||||
if(WIN32)
|
||||
set(MODULE_DESCRIPTION "OBS x264 encoder")
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in obs-x264.rc)
|
||||
list(APPEND obs-x264_SOURCES
|
||||
obs-x264.rc)
|
||||
endif()
|
||||
|
||||
add_library(obs-x264 MODULE
|
||||
${obs-x264_SOURCES})
|
||||
target_link_libraries(obs-x264
|
||||
|
|
|
|||
|
|
@ -13,6 +13,13 @@ set(rtmp-services_SOURCES
|
|||
rtmp-custom.c
|
||||
rtmp-services-main.c)
|
||||
|
||||
if(WIN32)
|
||||
set(MODULE_DESCRIPTION "OBS RTMP Services")
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in rtmp-services.rc)
|
||||
list(APPEND rtmp-services_SOURCES
|
||||
rtmp-services.rc)
|
||||
endif()
|
||||
|
||||
set(rtmp-services_HEADERS
|
||||
twitch.h
|
||||
younow.h
|
||||
|
|
|
|||
4
plugins/rtmp-services/data/package.json
Executable file → Normal file
4
plugins/rtmp-services/data/package.json
Executable file → Normal file
|
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
"url": "https://obsproject.com/obs2_update/rtmp-services",
|
||||
"version": 125,
|
||||
"version": 131,
|
||||
"files": [
|
||||
{
|
||||
"name": "services.json",
|
||||
"version": 125
|
||||
"version": 131
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
175
plugins/rtmp-services/data/services.json
Executable file → Normal file
175
plugins/rtmp-services/data/services.json
Executable file → Normal file
|
|
@ -893,57 +893,61 @@
|
|||
"name": "Castr.io",
|
||||
"servers": [
|
||||
{
|
||||
"name": "Chicago US",
|
||||
"name": "US-East (Chicago, IL)",
|
||||
"url": "rtmp://cg.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "Los Angeles US",
|
||||
"url": "rtmp://la.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "New York US",
|
||||
"name": "US-East (New York, NY)",
|
||||
"url": "rtmp://ny.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "Miami US",
|
||||
"name": "US-East (Miami, FL)",
|
||||
"url": "rtmp://mi.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "Montreal CA",
|
||||
"name": "US-West (Seattle, WA)",
|
||||
"url": "rtmp://se.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "US-West (Los Angeles, CA)",
|
||||
"url": "rtmp://la.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "US-Central (Dallas, TX)",
|
||||
"url": "rtmp://da.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "NA-East (Toronto, CA)",
|
||||
"url": "rtmp://qc.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "London UK",
|
||||
"url": "rtmp://uk.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "Frankfurt DE",
|
||||
"url": "rtmp://de.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "Frankfurt DE 2",
|
||||
"url": "rtmp://fr.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "Moscow RU",
|
||||
"url": "rtmp://ru.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "Singapore",
|
||||
"url": "rtmp://sg.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "Sydney AU",
|
||||
"url": "rtmp://au.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "Brazil",
|
||||
"name": "SA (Sao Paulo, BR)",
|
||||
"url": "rtmp://br.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "India",
|
||||
"name": "EU-West (London, UK)",
|
||||
"url": "rtmp://uk.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "EU-Central (Frankfurt, DE)",
|
||||
"url": "rtmp://fr.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "Russia (Moscow)",
|
||||
"url": "rtmp://ru.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "Asia (Singapore)",
|
||||
"url": "rtmp://sg.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "Asia (India)",
|
||||
"url": "rtmp://in.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "Australia (Sydney)",
|
||||
"url": "rtmp://au.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "US Central",
|
||||
"url": "rtmp://us-central.castr.io/static"
|
||||
|
|
@ -975,10 +979,6 @@
|
|||
{
|
||||
"name": "Singapore",
|
||||
"url": "rtmp://sg-central.castr.io/static"
|
||||
},
|
||||
{
|
||||
"name": "India",
|
||||
"url": "rtmp://in.castr.io/static"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
|
|
@ -1128,7 +1128,7 @@
|
|||
"servers": [
|
||||
{
|
||||
"name": "Auto",
|
||||
"url": "rtmp://s-sd.stripcdn.com/ext"
|
||||
"url": "rtmp://s-sd.stripst.com/ext"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
|
|
@ -1494,14 +1494,28 @@
|
|||
"name": "Bongacams",
|
||||
"servers": [
|
||||
{
|
||||
"name": "Default",
|
||||
"url": "rtmp://origin.bcrncdn.com:1934/live"
|
||||
"name": "Automatic / Default",
|
||||
"url": "rtmp://auto.origin.gnsbc.com:1934/live"
|
||||
},
|
||||
{
|
||||
"name": "Automatic / Backup",
|
||||
"url": "rtmp://origin.bcvidorigin.com:1934/live"
|
||||
},
|
||||
{
|
||||
"name": "Europe",
|
||||
"url": "rtmp://z-eu.origin.gnsbc.com:1934/live"
|
||||
},
|
||||
{
|
||||
"name": "North America",
|
||||
"url": "rtmp://z-us.origin.gnsbc.com:1934/live"
|
||||
}
|
||||
],
|
||||
"recommend": {
|
||||
"keyint": 2,
|
||||
"max video bitrate": 6000,
|
||||
"max audio bitrate": 192
|
||||
"max audio bitrate": 192,
|
||||
"bframes": 0,
|
||||
"x264opts": "tune=zerolatency"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -1518,16 +1532,20 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"name": "ChathostessModels",
|
||||
"name": "Chathostess",
|
||||
"servers": [
|
||||
{
|
||||
"name": "ChathostessModels - Default",
|
||||
"name": "Chathostess - Default",
|
||||
"url": "rtmp://wowza01.foobarweb.com/cmschatsys_video"
|
||||
},
|
||||
{
|
||||
"name": "Chathostess - Backup",
|
||||
"url": "rtmp://wowza05.foobarweb.com/cmschatsys_video"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"keyint": 2,
|
||||
"max video bitrate": 3000,
|
||||
"max video bitrate": 3600,
|
||||
"max audio bitrate": 128
|
||||
}
|
||||
},
|
||||
|
|
@ -1733,6 +1751,73 @@
|
|||
"recommended": {
|
||||
"keyint": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "niconico, premium member (ニコニコ生放送 プレミアム会員)",
|
||||
"servers": [
|
||||
{
|
||||
"name": "Default",
|
||||
"url": "rtmp://aliveorigin.dmc.nico/named_input"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"keyint": 2,
|
||||
"profile": "high",
|
||||
"max audio bitrate": 192,
|
||||
"max video bitrate": 5808,
|
||||
"x264opts": "tune=zerolatency"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "niconico, free member (ニコニコ生放送 一般会員)",
|
||||
"servers": [
|
||||
{
|
||||
"name": "Default",
|
||||
"url": "rtmp://aliveorigin.dmc.nico/named_input"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"keyint": 2,
|
||||
"profile": "high",
|
||||
"max audio bitrate": 96,
|
||||
"max video bitrate": 904,
|
||||
"x264opts": "tune=zerolatency"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "WASD.TV",
|
||||
"servers": [
|
||||
{
|
||||
"name": "Automatic",
|
||||
"url": "rtmp://push.rtmp.wasd.tv/live"
|
||||
},
|
||||
{
|
||||
"name": "Russia, Moscow",
|
||||
"url": "rtmp://ru-moscow.rtmp.wasd.tv/live"
|
||||
},
|
||||
{
|
||||
"name": "Germany, Frankfurt",
|
||||
"url": "rtmp://de-frankfurt.rtmp.wasd.tv/live"
|
||||
},
|
||||
{
|
||||
"name": "Finland, Helsinki",
|
||||
"url": "rtmp://fi-helsinki.rtmp.wasd.tv/live"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"keyint": 2,
|
||||
"max video bitrate": 10000,
|
||||
"max audio bitrate": 192
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "VirtWish",
|
||||
"servers": [
|
||||
{
|
||||
"name": "Default",
|
||||
"url": "rtmp://rtmp.virtwish.com/live"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ static void rtmp_custom_update(void *data, obs_data_t *settings)
|
|||
|
||||
bfree(service->server);
|
||||
bfree(service->key);
|
||||
bfree(service->username);
|
||||
bfree(service->password);
|
||||
|
||||
service->server = bstrdup(obs_data_get_string(settings, "server"));
|
||||
service->key = bstrdup(obs_data_get_string(settings, "key"));
|
||||
|
|
|
|||
|
|
@ -14,9 +14,12 @@ elseif(NOT FREETYPE_FOUND)
|
|||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(MODULE_DESCRIPTION "OBS Freetype text module")
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in text-freetype2.rc)
|
||||
set(text-freetype2_PLATFORM_SOURCES
|
||||
find-font.c
|
||||
find-font-windows.c)
|
||||
find-font-windows.c
|
||||
text-freetype2.rc)
|
||||
elseif(APPLE)
|
||||
find_package(Iconv QUIET)
|
||||
if(NOT ICONV_FOUND AND ENABLE_FREETYPE)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,13 @@ set(vlc-video_SOURCES
|
|||
vlc-video-source.c
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(MODULE_DESCRIPTION "OBS VLC module")
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/winrc/obs-module.rc.in vlc-video.rc)
|
||||
list(APPEND vlc-video_SOURCES
|
||||
vlc-video.rc)
|
||||
endif()
|
||||
|
||||
add_library(vlc-video MODULE
|
||||
${vlc-video_SOURCES}
|
||||
${vlc-video_HEADERS})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue