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,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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue