mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-11-30 15:23:01 +00:00
project: Merged FFmpeg Encoders Step 2
This commit is contained in:
parent
3eea289679
commit
0a16ce07dc
61 changed files with 1979 additions and 3442 deletions
|
@ -397,14 +397,14 @@ set(PROJECT_PRIVATE_SOURCE
|
||||||
"${PROJECT_SOURCE_DIR}/source/obs/gs/gs-vertex.cpp"
|
"${PROJECT_SOURCE_DIR}/source/obs/gs/gs-vertex.cpp"
|
||||||
"${PROJECT_SOURCE_DIR}/source/obs/gs/gs-vertexbuffer.hpp"
|
"${PROJECT_SOURCE_DIR}/source/obs/gs/gs-vertexbuffer.hpp"
|
||||||
"${PROJECT_SOURCE_DIR}/source/obs/gs/gs-vertexbuffer.cpp"
|
"${PROJECT_SOURCE_DIR}/source/obs/gs/gs-vertexbuffer.cpp"
|
||||||
"${PROJECT_SOURCE_DIR}/source/obs/obs-tools.hpp"
|
|
||||||
"${PROJECT_SOURCE_DIR}/source/obs/obs-tools.cpp"
|
|
||||||
"${PROJECT_SOURCE_DIR}/source/obs/obs-source.hpp"
|
"${PROJECT_SOURCE_DIR}/source/obs/obs-source.hpp"
|
||||||
"${PROJECT_SOURCE_DIR}/source/obs/obs-source.cpp"
|
"${PROJECT_SOURCE_DIR}/source/obs/obs-source.cpp"
|
||||||
"${PROJECT_SOURCE_DIR}/source/obs/obs-source-factory.hpp"
|
"${PROJECT_SOURCE_DIR}/source/obs/obs-source-factory.hpp"
|
||||||
"${PROJECT_SOURCE_DIR}/source/obs/obs-source-factory.cpp"
|
"${PROJECT_SOURCE_DIR}/source/obs/obs-source-factory.cpp"
|
||||||
"${PROJECT_SOURCE_DIR}/source/obs/obs-source-tracker.hpp"
|
"${PROJECT_SOURCE_DIR}/source/obs/obs-source-tracker.hpp"
|
||||||
"${PROJECT_SOURCE_DIR}/source/obs/obs-source-tracker.cpp"
|
"${PROJECT_SOURCE_DIR}/source/obs/obs-source-tracker.cpp"
|
||||||
|
"${PROJECT_SOURCE_DIR}/source/obs/obs-tools.hpp"
|
||||||
|
"${PROJECT_SOURCE_DIR}/source/obs/obs-tools.cpp"
|
||||||
|
|
||||||
# Sources
|
# Sources
|
||||||
"${PROJECT_SOURCE_DIR}/source/sources/source-mirror.hpp"
|
"${PROJECT_SOURCE_DIR}/source/sources/source-mirror.hpp"
|
||||||
|
@ -430,7 +430,7 @@ set(PROJECT_PRIVATE_SOURCE
|
||||||
|
|
||||||
# Transitions
|
# Transitions
|
||||||
|
|
||||||
# ffmpeg
|
# FFmpeg
|
||||||
"${PROJECT_SOURCE_DIR}/source/ffmpeg/avframe-queue.cpp"
|
"${PROJECT_SOURCE_DIR}/source/ffmpeg/avframe-queue.cpp"
|
||||||
"${PROJECT_SOURCE_DIR}/source/ffmpeg/avframe-queue.hpp"
|
"${PROJECT_SOURCE_DIR}/source/ffmpeg/avframe-queue.hpp"
|
||||||
"${PROJECT_SOURCE_DIR}/source/ffmpeg/swscale.hpp"
|
"${PROJECT_SOURCE_DIR}/source/ffmpeg/swscale.hpp"
|
||||||
|
@ -439,12 +439,12 @@ set(PROJECT_PRIVATE_SOURCE
|
||||||
"${PROJECT_SOURCE_DIR}/source/ffmpeg/tools.cpp"
|
"${PROJECT_SOURCE_DIR}/source/ffmpeg/tools.cpp"
|
||||||
"${PROJECT_SOURCE_DIR}/source/ffmpeg/hwapi/base.hpp"
|
"${PROJECT_SOURCE_DIR}/source/ffmpeg/hwapi/base.hpp"
|
||||||
"${PROJECT_SOURCE_DIR}/source/ffmpeg/hwapi/base.cpp"
|
"${PROJECT_SOURCE_DIR}/source/ffmpeg/hwapi/base.cpp"
|
||||||
"${PROJECT_SOURCE_DIR}/source/ffmpeg/hwapi/d3d11.hpp"
|
"${PROJECT_SOURCE_DIR}/source/ffmpeg/hwapi/d3d11.hpp"
|
||||||
"${PROJECT_SOURCE_DIR}/source/ffmpeg/hwapi/d3d11.cpp"
|
"${PROJECT_SOURCE_DIR}/source/ffmpeg/hwapi/d3d11.cpp"
|
||||||
|
|
||||||
# Encoders
|
# Encoders
|
||||||
"${PROJECT_SOURCE_DIR}/source/encoders/encoder.hpp"
|
"${PROJECT_SOURCE_DIR}/source/encoders/ffmpeg-encoder.hpp"
|
||||||
"${PROJECT_SOURCE_DIR}/source/encoders/encoder.cpp"
|
"${PROJECT_SOURCE_DIR}/source/encoders/ffmpeg-encoder.cpp"
|
||||||
# Encoders/Codecs
|
# Encoders/Codecs
|
||||||
"${PROJECT_SOURCE_DIR}/source/encoders/codecs/hevc.hpp"
|
"${PROJECT_SOURCE_DIR}/source/encoders/codecs/hevc.hpp"
|
||||||
"${PROJECT_SOURCE_DIR}/source/encoders/codecs/hevc.cpp"
|
"${PROJECT_SOURCE_DIR}/source/encoders/codecs/hevc.cpp"
|
||||||
|
|
|
@ -17,23 +17,18 @@
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef STREAMEFFECTS_VERSION_HPP
|
|
||||||
#define STREAMEFFECTS_VERSION_HPP
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
|
|
||||||
#define STREAMEFFECTS_MAKE_VERSION(major,minor,patch,tweak) ((uint64_t(major) & 0xFFFFull) << 48ull) | ((uint64_t(minor) & 0xFFFFull) << 32ull) | ((uint64_t(patch) & 0xFFFFull) << 16ull) | ((uint64_t(tweak) & 0xFFFFull))
|
#define STREAMFX_MAKE_VERSION(major,minor,patch,tweak) ((uint64_t(major) & 0xFFFFull) << 48ull) | ((uint64_t(minor) & 0xFFFFull) << 32ull) | ((uint64_t(patch) & 0xFFFFull) << 16ull) | ((uint64_t(tweak) & 0xFFFFull))
|
||||||
|
|
||||||
#define STREAMEFFECTS_MASK_COMPAT 0xFFFFFFFF00000000ull
|
#define STREAMFX_MASK_COMPAT 0xFFFFFFFF00000000ull
|
||||||
#define STREAMEFFECTS_MASK_UPDATE 0xFFFFFFFFFFFF0000ull
|
#define STREAMFX_MASK_UPDATE 0xFFFFFFFFFFFF0000ull
|
||||||
|
|
||||||
#define STREAMEFFECTS_COMMIT "@PROJECT_COMMIT@"
|
#define STREAMFX_COMMIT "@PROJECT_COMMIT@"
|
||||||
#define STREAMEFFECTS_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
|
#define STREAMFX_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
|
||||||
#define STREAMEFFECTS_VERSION_MINOR @PROJECT_VERSION_MINOR@
|
#define STREAMFX_VERSION_MINOR @PROJECT_VERSION_MINOR@
|
||||||
#define STREAMEFFECTS_VERSION_PATCH @PROJECT_VERSION_PATCH@
|
#define STREAMFX_VERSION_PATCH @PROJECT_VERSION_PATCH@
|
||||||
#define STREAMEFFECTS_VERSION_BUILD @PROJECT_VERSION_TWEAK@
|
#define STREAMFX_VERSION_BUILD @PROJECT_VERSION_TWEAK@
|
||||||
#define STREAMEFFECTS_VERSION STREAMEFFECTS_MAKE_VERSION(STREAMEFFECTS_VERSION_MAJOR, STREAMEFFECTS_VERSION_MINOR, STREAMEFFECTS_VERSION_PATCH, STREAMEFFECTS_VERSION_BUILD)
|
#define STREAMFX_VERSION STREAMFX_MAKE_VERSION(STREAMFX_VERSION_MAJOR, STREAMFX_VERSION_MINOR, STREAMFX_VERSION_PATCH, STREAMFX_VERSION_BUILD)
|
||||||
#define STREAMEFFECTS_VERSION_STRING "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.@PROJECT_VERSION_TWEAK@-@PROJECT_COMMIT@"
|
#define STREAMFX_VERSION_STRING "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.@PROJECT_VERSION_TWEAK@-@PROJECT_COMMIT@"
|
||||||
|
|
||||||
#endif STREAMEFFECTS_VERSION_HPP
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ State.Disabled="Disabled"
|
||||||
State.Enabled="Enabled"
|
State.Enabled="Enabled"
|
||||||
State.Manual="Manual"
|
State.Manual="Manual"
|
||||||
State.Automatic="Automatic"
|
State.Automatic="Automatic"
|
||||||
|
State.Default="Default"
|
||||||
|
|
||||||
# Blur
|
# Blur
|
||||||
Blur.Type.Box="Box"
|
Blur.Type.Box="Box"
|
||||||
|
@ -333,3 +334,141 @@ Source.Mirror.Scaling.Alignment.Description="How should the source be aligned wi
|
||||||
|
|
||||||
# Source - Shader
|
# Source - Shader
|
||||||
Source.Shader="Shader"
|
Source.Shader="Shader"
|
||||||
|
|
||||||
|
# Codec: H264
|
||||||
|
Codec.H264="H264"
|
||||||
|
Codec.H264.Profile="Profile"
|
||||||
|
Codec.H264.Profile.baseline="Baseline"
|
||||||
|
Codec.H264.Profile.main="Main"
|
||||||
|
Codec.H264.Profile.high="High"
|
||||||
|
Codec.H264.Profile.high444p="High 4:4:4 Predictive"
|
||||||
|
Codec.H264.Profile.Description="H.264 profile determines which features of the codec can be used.\nHigh 4:4:4 Predictive is required for YUV 4:4:4 color space."
|
||||||
|
Codec.H264.Level="Level"
|
||||||
|
Codec.H264.Level.Description="Level determines the upper limits of resolution, frame rate and bitrate for the video."
|
||||||
|
|
||||||
|
# Codec: HEVC
|
||||||
|
Codec.HEVC="HEVC"
|
||||||
|
Codec.HEVC.Profile="Profile"
|
||||||
|
Codec.HEVC.Profile.main="Main"
|
||||||
|
Codec.HEVC.Profile.main10="Main 10-bit"
|
||||||
|
Codec.HEVC.Profile.rext="Range Extended"
|
||||||
|
Codec.HEVC.Tier="Tier"
|
||||||
|
Codec.HEVC.Tier.main="Main"
|
||||||
|
Codec.HEVC.Tier.high="High"
|
||||||
|
Codec.HEVC.Level="Level"
|
||||||
|
Codec.HEVC.Level.Description="Level determines the upper limits of resolution, frame rate and bitrate for the video."
|
||||||
|
|
||||||
|
# Codec: Apple ProRes
|
||||||
|
Codec.ProRes.Profile="Profile"
|
||||||
|
Codec.ProRes.Profile.APCO="422 Proxy/PXY (APCO)"
|
||||||
|
Codec.ProRes.Profile.APCS="422 Light/LT (APCS)"
|
||||||
|
Codec.ProRes.Profile.APCN="422 Standard (APCN)"
|
||||||
|
Codec.ProRes.Profile.APCH="422 High Quality/HQ (APCH)"
|
||||||
|
Codec.ProRes.Profile.AP4H="4444 Standard (AP4H)"
|
||||||
|
Codec.ProRes.Profile.AP4X="4444 Extra Quality/XQ (AP4X)"
|
||||||
|
|
||||||
|
# Encoder: FFmpeg
|
||||||
|
Encoder.FFmpeg="FFmpeg Options"
|
||||||
|
Encoder.FFmpeg.CustomSettings="Custom Settings"
|
||||||
|
Encoder.FFmpeg.CustomSettings.Description="Override any options shown (or not shown) above with your own.\nThe format is similar to that of the FFmpeg command line:\n -key=value -key2=value2 -key3='quoted value'"
|
||||||
|
Encoder.FFmpeg.Threads="Number of Threads"
|
||||||
|
Encoder.FFmpeg.Threads.Description="The number of threads to use for encoding, if supported by the encoder.\nA value of 0 is equal to 'auto-detect' and may result in excessive CPU usage."
|
||||||
|
Encoder.FFmpeg.ColorFormat="Override Color Format"
|
||||||
|
Encoder.FFmpeg.ColorFormat.Description="Overriding the color format can unlock higher quality, but might cause additional stress.\nNot all encoders support all color formats, and you might end up causing errors or corrupted video due to this."
|
||||||
|
Encoder.FFmpeg.StandardCompliance="Standard Compliance"
|
||||||
|
Encoder.FFmpeg.StandardCompliance.Description="How strict should the encoder keep to the standard? A strictness below 'Normal' may cause issues with playback."
|
||||||
|
Encoder.FFmpeg.StandardCompliance.VeryStrict="Very Strict"
|
||||||
|
Encoder.FFmpeg.StandardCompliance.Strict="Strict"
|
||||||
|
Encoder.FFmpeg.StandardCompliance.Normal="Normal"
|
||||||
|
Encoder.FFmpeg.StandardCompliance.Unofficial="Unofficial"
|
||||||
|
Encoder.FFmpeg.StandardCompliance.Experimental="Experimental"
|
||||||
|
Encoder.FFmpeg.GPU="GPU"
|
||||||
|
Encoder.FFmpeg.GPU.Description="For multiple GPU systems, selects which GPU to use as the main encoder"
|
||||||
|
Encoder.FFmpeg.KeyFrames="Key Frames"
|
||||||
|
Encoder.FFmpeg.KeyFrames.IntervalType="Interval Type"
|
||||||
|
Encoder.FFmpeg.KeyFrames.IntervalType.Frames="Frames"
|
||||||
|
Encoder.FFmpeg.KeyFrames.IntervalType.Seconds="Seconds"
|
||||||
|
Encoder.FFmpeg.KeyFrames.IntervalType.Description="Keyframe interval type"
|
||||||
|
Encoder.FFmpeg.KeyFrames.Interval.Description="Distance between key frames, in frames or seconds."
|
||||||
|
Encoder.FFmpeg.KeyFrames.Interval="Interval"
|
||||||
|
|
||||||
|
# Encoder: NVENC
|
||||||
|
Encoder.NVENC.Preset="Preset"
|
||||||
|
Encoder.NVENC.Preset.Description="Presets are NVIDIA's preconfigured default settings."
|
||||||
|
Encoder.NVENC.Preset.Default="Default"
|
||||||
|
Encoder.NVENC.Preset.Slow="Slow"
|
||||||
|
Encoder.NVENC.Preset.Medium="Medium"
|
||||||
|
Encoder.NVENC.Preset.Fast="Fast"
|
||||||
|
Encoder.NVENC.Preset.HighPerformance="High Performance"
|
||||||
|
Encoder.NVENC.Preset.HighQuality="High Quality"
|
||||||
|
Encoder.NVENC.Preset.BluRayDisc="BluRay Disc"
|
||||||
|
Encoder.NVENC.Preset.LowLatency="Low Latency"
|
||||||
|
Encoder.NVENC.Preset.LowLatencyHighPerformance="Low Latency High Performance"
|
||||||
|
Encoder.NVENC.Preset.LowLatencyHighQuality="Low Latency High Quality"
|
||||||
|
Encoder.NVENC.Preset.Lossless="Lossless"
|
||||||
|
Encoder.NVENC.Preset.LosslessHighPerformance="Lossless High Performance"
|
||||||
|
Encoder.NVENC.RateControl="Rate Control Options"
|
||||||
|
Encoder.NVENC.RateControl.Mode="Mode"
|
||||||
|
Encoder.NVENC.RateControl.Mode.Description="Rate control mode selection"
|
||||||
|
Encoder.NVENC.RateControl.Mode.CQP="Constant Quantization Parameter"
|
||||||
|
Encoder.NVENC.RateControl.Mode.CQP.Description="A flat compression ratio with no regard for bit rates."
|
||||||
|
Encoder.NVENC.RateControl.Mode.VBR="Variable Bitrate"
|
||||||
|
Encoder.NVENC.RateControl.Mode.VBR.Description="Sacrifices quality to stay below the upper bitrate limit,\nor saves bitrate where possible."
|
||||||
|
Encoder.NVENC.RateControl.Mode.VBR_HQ="High Quality Variable Bitrate"
|
||||||
|
Encoder.NVENC.RateControl.Mode.VBR_HQ.Description="Variable Bitrate with two-pass encoding enabled by default."
|
||||||
|
Encoder.NVENC.RateControl.Mode.CBR="Constant Bitrate"
|
||||||
|
Encoder.NVENC.RateControl.Mode.CBR.Description="Compresses footage so that it matches the target bitrate over the duration of\none second. This comes at a cost in quality during high motion scenes or\nscenes with flickering brightness like often seen in RPGs."
|
||||||
|
Encoder.NVENC.RateControl.Mode.CBR_HQ="High Quality Constant Bitrate"
|
||||||
|
Encoder.NVENC.RateControl.Mode.CBR_HQ.Description="Constant Bitrate with two-pass encoding enabled by default."
|
||||||
|
Encoder.NVENC.RateControl.Mode.CBR_LD_HQ="Low Delay High Quality Constant Bitrate"
|
||||||
|
Encoder.NVENC.RateControl.Mode.CBR_LD_HQ.Description="Constant Bitrate optimized for lowest encoding latency."
|
||||||
|
Encoder.NVENC.RateControl.LookAhead="Look Ahead"
|
||||||
|
Encoder.NVENC.RateControl.LookAhead.Description="Look ahead this many frames while encoding to better distribute bitrate.\nImproves quality slightly at the cost of some GPU time.\nSet to 0 to disable."
|
||||||
|
Encoder.NVENC.RateControl.AdaptiveI="Adaptive I-Frames"
|
||||||
|
Encoder.NVENC.RateControl.AdaptiveI.Description="Enables adaptive I-Frame insertion.\nOnly has an effect when look ahead is set to a value other than 0."
|
||||||
|
Encoder.NVENC.RateControl.AdaptiveB="Adaptive B-Frames"
|
||||||
|
Encoder.NVENC.RateControl.AdaptiveB.Description="Enables adaptive B-Frame insertion.\nOnly has an effect when look ahead is set to a value other than 0."
|
||||||
|
Encoder.NVENC.RateControl.TwoPass="Two Pass"
|
||||||
|
Encoder.NVENC.RateControl.TwoPass.Description="Enable a secondary pass for encoding, which can help with quality and bitrate stability.\nImproves quality slightly at the cost of some GPU time.\nNvidia Turing hardware might actually see a quality degrade from this."
|
||||||
|
Encoder.NVENC.RateControl.Bitrate="Bitrate Limits"
|
||||||
|
Encoder.NVENC.RateControl.Bitrate.Target="Target Bitrate"
|
||||||
|
Encoder.NVENC.RateControl.Bitrate.Maximum="Maximum Bitrate"
|
||||||
|
Encoder.NVENC.RateControl.Quality="Enable Quality Limits"
|
||||||
|
Encoder.NVENC.RateControl.Quality.Minimum="Minimum Quality"
|
||||||
|
Encoder.NVENC.RateControl.Quality.Minimum.Description="Minimum quality to achieve, with values closer to 0 being better quality."
|
||||||
|
Encoder.NVENC.RateControl.Quality.Maximum="Maximum Quality"
|
||||||
|
Encoder.NVENC.RateControl.Quality.Maximum.Description="Maximum quality to achieve, with values closer to 0 being better quality.\nSet to -1 to disable the maximum restriction."
|
||||||
|
Encoder.NVENC.RateControl.Quality.Target="Target Quality"
|
||||||
|
Encoder.NVENC.RateControl.Quality.Target.Description="Target quality to achieve, with values closer to 0 being better quality.\nSet to 0 to disable the maximum restriction."
|
||||||
|
Encoder.NVENC.RateControl.QP="Quantization Parameters"
|
||||||
|
Encoder.NVENC.RateControl.QP.I="I-Frame QP"
|
||||||
|
Encoder.NVENC.RateControl.QP.I.Description="Quantization parameter for I-Frames.\nSmaller values mean better quality in exchange for higher bitrate, while higher values mean less bitrate in exchange for less quality."
|
||||||
|
Encoder.NVENC.RateControl.QP.I.Initial="Initial I-Frame QP"
|
||||||
|
Encoder.NVENC.RateControl.QP.I.Initial.Description="Initial B-Frame quantization parameter.\nSet to -1 to use the automatically detected value instead."
|
||||||
|
Encoder.NVENC.RateControl.QP.P="P-Frame QP"
|
||||||
|
Encoder.NVENC.RateControl.QP.P.Description="Quantization parameter for P-Frames.\nSmaller values mean better quality in exchange for higher bitrate, while higher values mean less bitrate in exchange for less quality."
|
||||||
|
Encoder.NVENC.RateControl.QP.P.Initial="Initial P-Frame QP"
|
||||||
|
Encoder.NVENC.RateControl.QP.P.Initial.Description="Initial P-Frame quantization parameter.\nSet to -1 to use the automatically detected value instead."
|
||||||
|
Encoder.NVENC.RateControl.QP.B="B-Frame QP"
|
||||||
|
Encoder.NVENC.RateControl.QP.B.Description="Quantization parameter for B-Frames.\nSmaller values mean better quality in exchange for higher bitrate, while higher values mean less bitrate in exchange for less quality."
|
||||||
|
Encoder.NVENC.RateControl.QP.B.Initial="Initial B-Frame QP"
|
||||||
|
Encoder.NVENC.RateControl.QP.B.Initial.Description="Initial B-Frame quantization parameter.\nSet to -1 to use the automatically detected value instead."
|
||||||
|
Encoder.NVENC.AQ="Adaptive Quantization"
|
||||||
|
Encoder.NVENC.AQ.Spatial="Spatial Adaptive Quantization"
|
||||||
|
Encoder.NVENC.AQ.Spatial.Description="Enable spatial adaptive quantization, also sometimes referred to as Psychovisual Adaptive Quantization."
|
||||||
|
Encoder.NVENC.AQ.Strength="Spatial AQ Strength"
|
||||||
|
Encoder.NVENC.AQ.Strength.Description="Strength of the spatial adaptive quantization.\nValues closer to 15 mean more aggressive, while values closer to 1 mean more relaxed."
|
||||||
|
Encoder.NVENC.AQ.Temporal="Temporal Adaptive Quantization"
|
||||||
|
Encoder.NVENC.AQ.Temporal.Description="Enable temporal adaptive quantization."
|
||||||
|
Encoder.NVENC.Other="Other Options"
|
||||||
|
Encoder.NVENC.Other.BFrames="Maximum B-Frames"
|
||||||
|
Encoder.NVENC.Other.BFrames.Description="Maximum number of B-Frames to insert into the encoded bitstream.\nActual number of B-Frames may be lower depending on content and lookahead settings.\nOnly Turing NVENC supports B-Frames for HEVC."
|
||||||
|
Encoder.NVENC.Other.BFrameReferenceMode="B-Frame Reference Mode"
|
||||||
|
Encoder.NVENC.Other.BFrameReferenceMode.Each="Each B-Frame will be used for references"
|
||||||
|
Encoder.NVENC.Other.BFrameReferenceMode.Middle="Only (# of B-Frames)/2 will be used for references"
|
||||||
|
Encoder.NVENC.Other.ZeroLatency="Zero Latency"
|
||||||
|
Encoder.NVENC.Other.ZeroLatency.Description="Enable zero latency operation, which ensures that there is no reordering delay."
|
||||||
|
Encoder.NVENC.Other.WeightedPrediction="Weighted Prediction"
|
||||||
|
Encoder.NVENC.Other.WeightedPrediction.Description="Enable weighted prediction for encoding.\nCan't be used with B-Frames."
|
||||||
|
Encoder.NVENC.Other.NonReferencePFrames="Non-reference P-Frames"
|
||||||
|
Encoder.NVENC.Other.NonReferencePFrames.Description="Enable the automatic insertion of non-reference P-Frames."
|
||||||
|
|
|
@ -27,41 +27,37 @@
|
||||||
#define P_H264_PROFILE "Codec.H264.Profile"
|
#define P_H264_PROFILE "Codec.H264.Profile"
|
||||||
#define P_H264_LEVEL "Codec.H264.Level"
|
#define P_H264_LEVEL "Codec.H264.Level"
|
||||||
|
|
||||||
namespace obsffmpeg {
|
namespace encoder::codec::h264 {
|
||||||
namespace codecs {
|
enum class profile {
|
||||||
namespace h264 {
|
CONSTRAINED_BASELINE,
|
||||||
enum class profile {
|
BASELINE,
|
||||||
CONSTRAINED_BASELINE,
|
MAIN,
|
||||||
BASELINE,
|
HIGH,
|
||||||
MAIN,
|
HIGH444_PREDICTIVE,
|
||||||
HIGH,
|
UNKNOWN = -1,
|
||||||
HIGH444_PREDICTIVE,
|
};
|
||||||
UNKNOWN = -1,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class level {
|
enum class level {
|
||||||
L1_0 = 10,
|
L1_0 = 10,
|
||||||
L1_0b,
|
L1_0b,
|
||||||
L1_1,
|
L1_1,
|
||||||
L1_2,
|
L1_2,
|
||||||
L1_3,
|
L1_3,
|
||||||
L2_0 = 20,
|
L2_0 = 20,
|
||||||
L2_1,
|
L2_1,
|
||||||
L2_2,
|
L2_2,
|
||||||
L3_0 = 30,
|
L3_0 = 30,
|
||||||
L3_1,
|
L3_1,
|
||||||
L3_2,
|
L3_2,
|
||||||
L4_0 = 40,
|
L4_0 = 40,
|
||||||
L4_1,
|
L4_1,
|
||||||
L4_2,
|
L4_2,
|
||||||
L5_0 = 50,
|
L5_0 = 50,
|
||||||
L5_1,
|
L5_1,
|
||||||
L5_2,
|
L5_2,
|
||||||
L6_0 = 60,
|
L6_0 = 60,
|
||||||
L6_1,
|
L6_1,
|
||||||
L6_2,
|
L6_2,
|
||||||
UNKNOWN = -1,
|
UNKNOWN = -1,
|
||||||
};
|
};
|
||||||
} // namespace h264
|
} // namespace encoder::codec::h264
|
||||||
} // namespace codecs
|
|
||||||
} // namespace obsffmpeg
|
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#include "hevc.hpp"
|
#include "hevc.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
using namespace encoder::codec;
|
||||||
|
|
||||||
enum class nal_unit_type : uint8_t { // 6 bits
|
enum class nal_unit_type : uint8_t { // 6 bits
|
||||||
TRAIL_N = 0,
|
TRAIL_N = 0,
|
||||||
TRAIL_R = 1,
|
TRAIL_R = 1,
|
||||||
|
@ -104,7 +106,7 @@ struct hevc_nal {
|
||||||
|
|
||||||
bool is_nal(uint8_t* data, uint8_t* end)
|
bool is_nal(uint8_t* data, uint8_t* end)
|
||||||
{
|
{
|
||||||
size_t s = end - data;
|
size_t s = static_cast<size_t>(end - data);
|
||||||
if (s < 4)
|
if (s < 4)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -138,14 +140,14 @@ size_t get_nal_size(uint8_t* data, uint8_t* end)
|
||||||
{
|
{
|
||||||
uint8_t* ptr = data + 4;
|
uint8_t* ptr = data + 4;
|
||||||
if (!seek_to_nal(ptr, end)) {
|
if (!seek_to_nal(ptr, end)) {
|
||||||
return end - data;
|
return static_cast<size_t>(end - data);
|
||||||
}
|
}
|
||||||
return ptr - data;
|
return static_cast<size_t>(ptr - data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_discard_marker(uint8_t* data, uint8_t* end)
|
bool is_discard_marker(uint8_t* data, uint8_t* end)
|
||||||
{
|
{
|
||||||
size_t s = end - data;
|
size_t s = static_cast<size_t>(end - data);
|
||||||
if (s < 4)
|
if (s < 4)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -197,8 +199,7 @@ void progress_parse(uint8_t*& ptr, uint8_t* end, size_t& sz)
|
||||||
sz = get_nal_size(ptr, end);
|
sz = get_nal_size(ptr, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::codecs::hevc::extract_header_sei(uint8_t* data, size_t sz_data, std::vector<uint8_t>& header,
|
void hevc::extract_header_sei(uint8_t* data, size_t sz_data, std::vector<uint8_t>& header, std::vector<uint8_t>& sei)
|
||||||
std::vector<uint8_t>& sei)
|
|
||||||
{
|
{
|
||||||
uint8_t* ptr = data;
|
uint8_t* ptr = data;
|
||||||
uint8_t* end = data + sz_data;
|
uint8_t* end = data + sz_data;
|
||||||
|
@ -231,6 +232,8 @@ void obsffmpeg::codecs::hevc::extract_header_sei(uint8_t* data, size_t sz_data,
|
||||||
case nal_unit_type::SUFFIX_SEI:
|
case nal_unit_type::SUFFIX_SEI:
|
||||||
sei.insert(sei.end(), ptr, ptr + nal_sz);
|
sei.insert(sei.end(), ptr, ptr + nal_sz);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,42 +28,36 @@
|
||||||
#define P_HEVC_TIER "Codec.HEVC.Tier"
|
#define P_HEVC_TIER "Codec.HEVC.Tier"
|
||||||
#define P_HEVC_LEVEL "Codec.HEVC.Level"
|
#define P_HEVC_LEVEL "Codec.HEVC.Level"
|
||||||
|
|
||||||
namespace obsffmpeg {
|
namespace encoder::codec::hevc {
|
||||||
namespace codecs {
|
enum class profile {
|
||||||
namespace hevc {
|
MAIN,
|
||||||
enum class profile {
|
MAIN10,
|
||||||
MAIN,
|
RANGE_EXTENDED,
|
||||||
MAIN10,
|
UNKNOWN = -1,
|
||||||
RANGE_EXTENDED,
|
};
|
||||||
UNKNOWN = -1,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class tier {
|
enum class tier {
|
||||||
MAIN,
|
MAIN,
|
||||||
HIGH,
|
HIGH,
|
||||||
UNKNOWN = -1,
|
UNKNOWN = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class level {
|
enum class level {
|
||||||
L1_0 = 30,
|
L1_0 = 30,
|
||||||
L2_0 = 60,
|
L2_0 = 60,
|
||||||
L2_1 = 63,
|
L2_1 = 63,
|
||||||
L3_0 = 90,
|
L3_0 = 90,
|
||||||
L3_1 = 93,
|
L3_1 = 93,
|
||||||
L4_0 = 120,
|
L4_0 = 120,
|
||||||
L4_1 = 123,
|
L4_1 = 123,
|
||||||
L5_0 = 150,
|
L5_0 = 150,
|
||||||
L5_1 = 153,
|
L5_1 = 153,
|
||||||
L5_2 = 156,
|
L5_2 = 156,
|
||||||
L6_0 = 180,
|
L6_0 = 180,
|
||||||
L6_1 = 183,
|
L6_1 = 183,
|
||||||
L6_2 = 186,
|
L6_2 = 186,
|
||||||
UNKNOWN = -1,
|
UNKNOWN = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
void extract_header_sei(uint8_t* data, size_t sz_data, std::vector<uint8_t>& header,
|
void extract_header_sei(uint8_t* data, size_t sz_data, std::vector<uint8_t>& header, std::vector<uint8_t>& sei);
|
||||||
std::vector<uint8_t>& sei);
|
} // namespace encoder::codec::hevc
|
||||||
|
|
||||||
} // namespace hevc
|
|
||||||
} // namespace codecs
|
|
||||||
} // namespace obsffmpeg
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,164 +0,0 @@
|
||||||
// FFMPEG Video Encoder Integration for OBS Studio
|
|
||||||
// Copyright (c) 2019 Michael Fabian Dirks <info@xaymar.com>
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <mutex>
|
|
||||||
#include <queue>
|
|
||||||
#include <stack>
|
|
||||||
#include <thread>
|
|
||||||
#include <vector>
|
|
||||||
#include "ffmpeg/avframe-queue.hpp"
|
|
||||||
#include "ffmpeg/swscale.hpp"
|
|
||||||
#include "hwapi/base.hpp"
|
|
||||||
#include "ui/handler.hpp"
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <obs-properties.h>
|
|
||||||
#include <obs.h>
|
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable : 4244)
|
|
||||||
#include <libavcodec/avcodec.h>
|
|
||||||
#include <libavutil/frame.h>
|
|
||||||
#pragma warning(pop)
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace obsffmpeg {
|
|
||||||
class unsupported_gpu_exception : public std::runtime_error {
|
|
||||||
public:
|
|
||||||
unsupported_gpu_exception(const std::string& reason) : runtime_error(reason) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct encoder_info {
|
|
||||||
std::string uid;
|
|
||||||
std::string codec;
|
|
||||||
std::string readable_name;
|
|
||||||
obs_encoder_info oei = {0};
|
|
||||||
};
|
|
||||||
|
|
||||||
class encoder_factory {
|
|
||||||
encoder_info info;
|
|
||||||
encoder_info info_fallback;
|
|
||||||
const AVCodec* avcodec_ptr;
|
|
||||||
|
|
||||||
std::shared_ptr<obsffmpeg::ui::handler> _handler;
|
|
||||||
|
|
||||||
public:
|
|
||||||
encoder_factory(const AVCodec* codec);
|
|
||||||
virtual ~encoder_factory();
|
|
||||||
|
|
||||||
void register_encoder();
|
|
||||||
|
|
||||||
void get_defaults(obs_data_t* settings, bool hw_encoder = false);
|
|
||||||
|
|
||||||
void get_properties(obs_properties_t* props, bool hw_encoder = false);
|
|
||||||
|
|
||||||
const AVCodec* get_avcodec();
|
|
||||||
|
|
||||||
const encoder_info& get_info();
|
|
||||||
|
|
||||||
const encoder_info& get_fallback();
|
|
||||||
};
|
|
||||||
|
|
||||||
class encoder {
|
|
||||||
obs_encoder_t* _self;
|
|
||||||
encoder_factory* _factory;
|
|
||||||
|
|
||||||
const AVCodec* _codec;
|
|
||||||
AVCodecContext* _context;
|
|
||||||
|
|
||||||
std::shared_ptr<obsffmpeg::ui::handler> _handler;
|
|
||||||
|
|
||||||
std::shared_ptr<obsffmpeg::hwapi::base> _hwapi;
|
|
||||||
std::shared_ptr<obsffmpeg::hwapi::instance> _hwinst;
|
|
||||||
|
|
||||||
ffmpeg::swscale _swscale;
|
|
||||||
AVPacket _current_packet;
|
|
||||||
|
|
||||||
size_t _lag_in_frames;
|
|
||||||
size_t _count_send_frames;
|
|
||||||
|
|
||||||
// Extra Data
|
|
||||||
bool _have_first_frame;
|
|
||||||
std::vector<uint8_t> _extra_data;
|
|
||||||
std::vector<uint8_t> _sei_data;
|
|
||||||
|
|
||||||
// Frame Stack and Queue
|
|
||||||
std::stack<std::shared_ptr<AVFrame>> _free_frames;
|
|
||||||
std::queue<std::shared_ptr<AVFrame>> _used_frames;
|
|
||||||
std::chrono::high_resolution_clock::time_point _free_frames_last_used;
|
|
||||||
|
|
||||||
void initialize_sw(obs_data_t* settings);
|
|
||||||
void initialize_hw(obs_data_t* settings);
|
|
||||||
|
|
||||||
void push_free_frame(std::shared_ptr<AVFrame> frame);
|
|
||||||
std::shared_ptr<AVFrame> pop_free_frame();
|
|
||||||
|
|
||||||
void push_used_frame(std::shared_ptr<AVFrame> frame);
|
|
||||||
std::shared_ptr<AVFrame> pop_used_frame();
|
|
||||||
|
|
||||||
public:
|
|
||||||
encoder(obs_data_t* settings, obs_encoder_t* encoder, bool is_texture_encode = false);
|
|
||||||
virtual ~encoder();
|
|
||||||
|
|
||||||
public: // OBS API
|
|
||||||
// Shared
|
|
||||||
void get_properties(obs_properties_t* props, bool hw_encode = false);
|
|
||||||
|
|
||||||
bool update(obs_data_t* settings);
|
|
||||||
|
|
||||||
// Audio only
|
|
||||||
void get_audio_info(struct audio_convert_info* info);
|
|
||||||
|
|
||||||
size_t get_frame_size();
|
|
||||||
|
|
||||||
bool audio_encode(struct encoder_frame* frame, struct encoder_packet* packet, bool* received_packet);
|
|
||||||
|
|
||||||
// Video only
|
|
||||||
void get_video_info(struct video_scale_info* info);
|
|
||||||
|
|
||||||
bool get_sei_data(uint8_t** sei_data, size_t* size);
|
|
||||||
|
|
||||||
bool get_extra_data(uint8_t** extra_data, size_t* size);
|
|
||||||
|
|
||||||
bool video_encode(struct encoder_frame* frame, struct encoder_packet* packet, bool* received_packet);
|
|
||||||
|
|
||||||
bool video_encode_texture(uint32_t handle, int64_t pts, uint64_t lock_key, uint64_t* next_key,
|
|
||||||
struct encoder_packet* packet, bool* received_packet);
|
|
||||||
|
|
||||||
int receive_packet(bool* received_packet, struct encoder_packet* packet);
|
|
||||||
|
|
||||||
int send_frame(std::shared_ptr<AVFrame> frame);
|
|
||||||
|
|
||||||
bool encode_avframe(std::shared_ptr<AVFrame> frame, struct encoder_packet* packet,
|
|
||||||
bool* received_packet);
|
|
||||||
|
|
||||||
public: // Handler API
|
|
||||||
bool is_hardware_encode();
|
|
||||||
|
|
||||||
const AVCodec* get_avcodec();
|
|
||||||
|
|
||||||
const AVCodecContext* get_avcodeccontext();
|
|
||||||
|
|
||||||
void parse_ffmpeg_commandline(std::string text);
|
|
||||||
};
|
|
||||||
} // namespace obsffmpeg
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
#include "handler.hpp"
|
#include "handler.hpp"
|
||||||
#include "plugin.hpp"
|
#include "plugin.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
@ -35,7 +36,9 @@ extern "C" {
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::debug_handler::get_defaults(obs_data_t*, const AVCodec*, AVCodecContext*, bool) {}
|
using namespace encoder::ffmpeg::handler;
|
||||||
|
|
||||||
|
void debug_handler::get_defaults(obs_data_t*, const AVCodec*, AVCodecContext*, bool) {}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::string to_string(T value){};
|
std::string to_string(T value){};
|
||||||
|
@ -64,8 +67,7 @@ std::string to_string(double_t value)
|
||||||
return std::string(buf.data(), buf.data() + buf.size());
|
return std::string(buf.data(), buf.data() + buf.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::debug_handler::get_properties(obs_properties_t*, const AVCodec* codec, AVCodecContext* context,
|
void debug_handler::get_properties(obs_properties_t*, const AVCodec* codec, AVCodecContext* context, bool)
|
||||||
bool)
|
|
||||||
{
|
{
|
||||||
if (context)
|
if (context)
|
||||||
return;
|
return;
|
||||||
|
@ -76,28 +78,28 @@ void obsffmpeg::ui::debug_handler::get_properties(obs_properties_t*, const AVCod
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PLOG_INFO("Options for '%s':", codec->name);
|
LOG_INFO("Options for '%s':", codec->name);
|
||||||
|
|
||||||
std::pair<AVOptionType, std::string> opt_type_name[] = {
|
std::pair<AVOptionType, std::string> opt_type_name[] = {
|
||||||
{AV_OPT_TYPE_FLAGS, "Flags"},
|
{AV_OPT_TYPE_FLAGS, "Flags"},
|
||||||
{AV_OPT_TYPE_INT, "Int"},
|
{AV_OPT_TYPE_INT, "Int"},
|
||||||
{AV_OPT_TYPE_INT64, "Int64"},
|
{AV_OPT_TYPE_INT64, "Int64"},
|
||||||
{AV_OPT_TYPE_DOUBLE, "Double"},
|
{AV_OPT_TYPE_DOUBLE, "Double"},
|
||||||
{AV_OPT_TYPE_FLOAT, "Float"},
|
{AV_OPT_TYPE_FLOAT, "Float"},
|
||||||
{AV_OPT_TYPE_STRING, "String"},
|
{AV_OPT_TYPE_STRING, "String"},
|
||||||
{AV_OPT_TYPE_RATIONAL, "Rational"},
|
{AV_OPT_TYPE_RATIONAL, "Rational"},
|
||||||
{AV_OPT_TYPE_BINARY, "Binary"},
|
{AV_OPT_TYPE_BINARY, "Binary"},
|
||||||
{AV_OPT_TYPE_DICT, "Dictionary"},
|
{AV_OPT_TYPE_DICT, "Dictionary"},
|
||||||
{AV_OPT_TYPE_UINT64, "Unsigned Int64"},
|
{AV_OPT_TYPE_UINT64, "Unsigned Int64"},
|
||||||
{AV_OPT_TYPE_CONST, "Constant"},
|
{AV_OPT_TYPE_CONST, "Constant"},
|
||||||
{AV_OPT_TYPE_IMAGE_SIZE, "Image Size"},
|
{AV_OPT_TYPE_IMAGE_SIZE, "Image Size"},
|
||||||
{AV_OPT_TYPE_PIXEL_FMT, "Pixel Format"},
|
{AV_OPT_TYPE_PIXEL_FMT, "Pixel Format"},
|
||||||
{AV_OPT_TYPE_SAMPLE_FMT, "Sample Format"},
|
{AV_OPT_TYPE_SAMPLE_FMT, "Sample Format"},
|
||||||
{AV_OPT_TYPE_VIDEO_RATE, "Video Rate"},
|
{AV_OPT_TYPE_VIDEO_RATE, "Video Rate"},
|
||||||
{AV_OPT_TYPE_DURATION, "Duration"},
|
{AV_OPT_TYPE_DURATION, "Duration"},
|
||||||
{AV_OPT_TYPE_COLOR, "Color"},
|
{AV_OPT_TYPE_COLOR, "Color"},
|
||||||
{AV_OPT_TYPE_CHANNEL_LAYOUT, "Layout"},
|
{AV_OPT_TYPE_CHANNEL_LAYOUT, "Layout"},
|
||||||
{AV_OPT_TYPE_BOOL, "Bool"},
|
{AV_OPT_TYPE_BOOL, "Bool"},
|
||||||
};
|
};
|
||||||
std::map<std::string, AVOptionType> unit_types;
|
std::map<std::string, AVOptionType> unit_types;
|
||||||
|
|
||||||
|
@ -113,13 +115,12 @@ void obsffmpeg::ui::debug_handler::get_properties(obs_properties_t*, const AVCod
|
||||||
|
|
||||||
if (opt->type == AV_OPT_TYPE_CONST) {
|
if (opt->type == AV_OPT_TYPE_CONST) {
|
||||||
if (opt->unit == nullptr) {
|
if (opt->unit == nullptr) {
|
||||||
PLOG_INFO(" Constant '%s' and help text '%s' with unknown settings.", opt->name,
|
LOG_INFO(" Constant '%s' and help text '%s' with unknown settings.", opt->name, opt->help);
|
||||||
opt->help);
|
|
||||||
} else {
|
} else {
|
||||||
auto unit_type = unit_types.find(opt->unit);
|
auto unit_type = unit_types.find(opt->unit);
|
||||||
if (unit_type == unit_types.end()) {
|
if (unit_type == unit_types.end()) {
|
||||||
PLOG_INFO(" [%s] Flag '%s' and help text '%s' with value '%lld'.", opt->unit,
|
LOG_INFO(" [%s] Flag '%s' and help text '%s' with value '%lld'.", opt->unit, opt->name, opt->help,
|
||||||
opt->name, opt->help, opt->default_val.i64);
|
opt->default_val.i64);
|
||||||
} else {
|
} else {
|
||||||
std::string out;
|
std::string out;
|
||||||
switch (unit_type->second) {
|
switch (unit_type->second) {
|
||||||
|
@ -153,8 +154,8 @@ void obsffmpeg::ui::debug_handler::get_properties(obs_properties_t*, const AVCod
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
PLOG_INFO(" [%s] Constant '%s' and help text '%s' with value '%s'.", opt->unit,
|
LOG_INFO(" [%s] Constant '%s' and help text '%s' with value '%s'.", opt->unit, opt->name,
|
||||||
opt->name, opt->help, out.c_str());
|
opt->help, out.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -198,13 +199,13 @@ void obsffmpeg::ui::debug_handler::get_properties(obs_properties_t*, const AVCod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PLOG_INFO(
|
LOG_INFO(
|
||||||
" Option '%s'%s%s%s with help '%s' of type '%s' with default value '%s', minimum '%s' and maximum '%s'.",
|
" Option '%s'%s%s%s with help '%s' of type '%s' with default value '%s', minimum '%s' and maximum "
|
||||||
opt->name, opt->unit ? " with unit (" : "", opt->unit ? opt->unit : "",
|
"'%s'.",
|
||||||
opt->unit ? ")" : "", opt->help, type_name.c_str(), out.c_str(), minimum.c_str(),
|
opt->name, opt->unit ? " with unit (" : "", opt->unit ? opt->unit : "", opt->unit ? ")" : "", opt->help,
|
||||||
maximum.c_str());
|
type_name.c_str(), out.c_str(), minimum.c_str(), maximum.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::debug_handler::update(obs_data_t*, const AVCodec*, AVCodecContext*) {}
|
void debug_handler::update(obs_data_t*, const AVCodec*, AVCodecContext*) {}
|
||||||
|
|
|
@ -22,18 +22,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "handler.hpp"
|
#include "handler.hpp"
|
||||||
|
|
||||||
namespace obsffmpeg {
|
namespace encoder::ffmpeg::handler {
|
||||||
namespace ui {
|
class debug_handler : public handler {
|
||||||
class debug_handler : public handler {
|
public:
|
||||||
public:
|
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context,
|
||||||
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context,
|
bool hw_encode) override;
|
||||||
bool hw_encode) override;
|
|
||||||
|
|
||||||
virtual void get_properties(obs_properties_t* props, const AVCodec* codec,
|
virtual void get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context,
|
||||||
AVCodecContext* context, bool hw_encode) override;
|
bool hw_encode) override;
|
||||||
|
|
||||||
virtual void update(obs_data_t* settings, const AVCodec* codec,
|
virtual void update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context) override;
|
||||||
AVCodecContext* context) override;
|
};
|
||||||
};
|
} // namespace encoder::ffmpeg::handler
|
||||||
} // namespace ui
|
|
||||||
} // namespace obsffmpeg
|
|
||||||
|
|
|
@ -20,27 +20,29 @@
|
||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
|
|
||||||
#include "handler.hpp"
|
#include "handler.hpp"
|
||||||
#include "encoder.hpp"
|
#include "../ffmpeg-encoder.hpp"
|
||||||
|
|
||||||
void obsffmpeg::ui::handler::adjust_encoder_info(obsffmpeg::encoder_factory*, obsffmpeg::encoder_info*,
|
void encoder::ffmpeg::handler::handler::adjust_encoder_info(encoder::ffmpeg::ffmpeg_factory*, ffmpeg_info*,
|
||||||
obsffmpeg::encoder_info*)
|
ffmpeg_info*)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void obsffmpeg::ui::handler::get_defaults(obs_data_t*, const AVCodec*, AVCodecContext*, bool) {}
|
void encoder::ffmpeg::handler::handler::get_defaults(obs_data_t*, const AVCodec*, AVCodecContext*, bool) {}
|
||||||
|
|
||||||
bool obsffmpeg::ui::handler::has_keyframe_support(obsffmpeg::encoder* instance)
|
bool encoder::ffmpeg::handler::handler::has_keyframe_support(ffmpeg_instance* instance)
|
||||||
{
|
{
|
||||||
return (instance->get_avcodec()->capabilities & AV_CODEC_CAP_INTRA_ONLY) == 0;
|
return (instance->get_avcodec()->capabilities & AV_CODEC_CAP_INTRA_ONLY) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::handler::get_properties(obs_properties_t*, const AVCodec*, AVCodecContext*, bool) {}
|
void encoder::ffmpeg::handler::handler::get_properties(obs_properties_t*, const AVCodec*, AVCodecContext*, bool) {}
|
||||||
|
|
||||||
void obsffmpeg::ui::handler::update(obs_data_t*, const AVCodec*, AVCodecContext*) {}
|
void encoder::ffmpeg::handler::handler::update(obs_data_t*, const AVCodec*, AVCodecContext*) {}
|
||||||
|
|
||||||
void obsffmpeg::ui::handler::override_update(obsffmpeg::encoder*, obs_data_t*) {}
|
void encoder::ffmpeg::handler::handler::override_update(ffmpeg_instance*, obs_data_t*) {}
|
||||||
|
|
||||||
void obsffmpeg::ui::handler::log_options(obs_data_t*, const AVCodec*, AVCodecContext*) {}
|
void encoder::ffmpeg::handler::handler::log_options(obs_data_t*, const AVCodec*, AVCodecContext*) {}
|
||||||
|
|
||||||
void obsffmpeg::ui::handler::override_colorformat(AVPixelFormat&, obs_data_t*, const AVCodec*, AVCodecContext*) {}
|
void encoder::ffmpeg::handler::handler::override_colorformat(AVPixelFormat&, obs_data_t*, const AVCodec*,
|
||||||
|
AVCodecContext*)
|
||||||
|
{}
|
||||||
|
|
||||||
void obsffmpeg::ui::handler::process_avpacket(AVPacket&, const AVCodec*, AVCodecContext*) {}
|
void encoder::ffmpeg::handler::handler::process_avpacket(AVPacket&, const AVCodec*, AVCodecContext*) {}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "hwapi/base.hpp"
|
#include "ffmpeg/hwapi/base.hpp"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <obs.h>
|
#include <obs.h>
|
||||||
|
@ -36,39 +36,37 @@ extern "C" {
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace obsffmpeg {
|
namespace encoder::ffmpeg {
|
||||||
struct encoder_info;
|
struct ffmpeg_info;
|
||||||
class encoder_factory;
|
class ffmpeg_factory;
|
||||||
class encoder;
|
class ffmpeg_instance;
|
||||||
|
|
||||||
namespace ui {
|
namespace handler {
|
||||||
class handler {
|
class handler {
|
||||||
public /*factory*/:
|
public /*factory*/:
|
||||||
virtual void adjust_encoder_info(obsffmpeg::encoder_factory* factory,
|
virtual void adjust_encoder_info(ffmpeg_factory* factory, ffmpeg_info* main, ffmpeg_info* fallback);
|
||||||
obsffmpeg::encoder_info* main,
|
|
||||||
obsffmpeg::encoder_info* fallback);
|
|
||||||
|
|
||||||
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context,
|
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context,
|
||||||
bool hw_encode);
|
bool hw_encode);
|
||||||
|
|
||||||
public /*settings*/:
|
public /*settings*/:
|
||||||
virtual bool has_keyframe_support(obsffmpeg::encoder* instance);
|
virtual bool has_keyframe_support(ffmpeg_instance* instance);
|
||||||
|
|
||||||
virtual void get_properties(obs_properties_t* props, const AVCodec* codec,
|
virtual void get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context,
|
||||||
AVCodecContext* context, bool hw_encode);
|
bool hw_encode);
|
||||||
|
|
||||||
virtual void update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
virtual void update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
||||||
|
|
||||||
virtual void override_update(obsffmpeg::encoder* instance, obs_data_t* settings);
|
virtual void override_update(ffmpeg_instance* instance, obs_data_t* settings);
|
||||||
|
|
||||||
virtual void log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
virtual void log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
||||||
|
|
||||||
public /*instance*/:
|
public /*instance*/:
|
||||||
|
|
||||||
virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings,
|
virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings, const AVCodec* codec,
|
||||||
const AVCodec* codec, AVCodecContext* context);
|
AVCodecContext* context);
|
||||||
|
|
||||||
virtual void process_avpacket(AVPacket& packet, const AVCodec* codec, AVCodecContext* context);
|
virtual void process_avpacket(AVPacket& packet, const AVCodec* codec, AVCodecContext* context);
|
||||||
};
|
};
|
||||||
} // namespace ui
|
} // namespace handler
|
||||||
} // namespace obsffmpeg
|
} // namespace encoder::ffmpeg
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
|
|
||||||
#include "nvenc_h264_handler.hpp"
|
#include "nvenc_h264_handler.hpp"
|
||||||
#include "codecs/h264.hpp"
|
#include "../codecs/h264.hpp"
|
||||||
#include "encoder.hpp"
|
#include "../ffmpeg-encoder.hpp"
|
||||||
#include "ffmpeg/tools.hpp"
|
#include "ffmpeg/tools.hpp"
|
||||||
#include "nvenc_shared.hpp"
|
#include "nvenc_shared.hpp"
|
||||||
#include "plugin.hpp"
|
#include "plugin.hpp"
|
||||||
|
@ -36,52 +36,43 @@ extern "C" {
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace obsffmpeg::codecs::h264;
|
using namespace encoder::ffmpeg::handler;
|
||||||
|
using namespace encoder::codec::h264;
|
||||||
|
|
||||||
std::map<profile, std::string> profiles{
|
std::map<profile, std::string> profiles{
|
||||||
{profile::BASELINE, "baseline"},
|
{profile::BASELINE, "baseline"},
|
||||||
{profile::MAIN, "main"},
|
{profile::MAIN, "main"},
|
||||||
{profile::HIGH, "high"},
|
{profile::HIGH, "high"},
|
||||||
{profile::HIGH444_PREDICTIVE, "high444p"},
|
{profile::HIGH444_PREDICTIVE, "high444p"},
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<level, std::string> levels{
|
std::map<level, std::string> levels{
|
||||||
{level::L1_0, "1.0"}, {level::L1_0b, "1.0b"}, {level::L1_1, "1.1"}, {level::L1_2, "1.2"}, {level::L1_3, "1.3"},
|
{level::L1_0, "1.0"}, {level::L1_0b, "1.0b"}, {level::L1_1, "1.1"}, {level::L1_2, "1.2"}, {level::L1_3, "1.3"},
|
||||||
{level::L2_0, "2.0"}, {level::L2_1, "2.1"}, {level::L2_2, "2.2"}, {level::L3_0, "3.0"}, {level::L3_1, "3.1"},
|
{level::L2_0, "2.0"}, {level::L2_1, "2.1"}, {level::L2_2, "2.2"}, {level::L3_0, "3.0"}, {level::L3_1, "3.1"},
|
||||||
{level::L3_2, "3.2"}, {level::L4_0, "4.0"}, {level::L4_1, "4.1"}, {level::L4_2, "4.2"}, {level::L5_0, "5.0"},
|
{level::L3_2, "3.2"}, {level::L4_0, "4.0"}, {level::L4_1, "4.1"}, {level::L4_2, "4.2"}, {level::L5_0, "5.0"},
|
||||||
{level::L5_1, "5.1"}, {level::L5_2, "5.2"},
|
{level::L5_1, "5.1"}, {level::L5_2, "5.2"},
|
||||||
};
|
};
|
||||||
|
|
||||||
INITIALIZER(nvenc_h264_handler_init)
|
void nvenc_h264_handler::adjust_encoder_info(ffmpeg_factory*, ffmpeg_info* main, ffmpeg_info* fallback)
|
||||||
{
|
|
||||||
obsffmpeg::initializers.push_back([]() {
|
|
||||||
obsffmpeg::register_codec_handler("h264_nvenc", std::make_shared<obsffmpeg::ui::nvenc_h264_handler>());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
void obsffmpeg::ui::nvenc_h264_handler::adjust_encoder_info(obsffmpeg::encoder_factory*, obsffmpeg::encoder_info* main,
|
|
||||||
obsffmpeg::encoder_info* fallback)
|
|
||||||
{
|
{
|
||||||
main->readable_name = "H.264/AVC NVidia NVENC (Hardware)";
|
main->readable_name = "H.264/AVC NVidia NVENC (Hardware)";
|
||||||
fallback->readable_name = "H.264/AVC NVidia NVENC (Software)";
|
fallback->readable_name = "H.264/AVC NVidia NVENC (Software)";
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::nvenc_h264_handler::get_defaults(obs_data_t* settings, const AVCodec* codec,
|
void nvenc_h264_handler::get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, bool)
|
||||||
AVCodecContext* context, bool)
|
|
||||||
{
|
{
|
||||||
nvenc::get_defaults(settings, codec, context);
|
nvenc::get_defaults(settings, codec, context);
|
||||||
|
|
||||||
obs_data_set_default_int(settings, P_H264_PROFILE, static_cast<int64_t>(codecs::h264::profile::HIGH));
|
obs_data_set_default_int(settings, P_H264_PROFILE, static_cast<int64_t>(profile::HIGH));
|
||||||
obs_data_set_default_int(settings, P_H264_LEVEL, static_cast<int64_t>(codecs::h264::level::UNKNOWN));
|
obs_data_set_default_int(settings, P_H264_LEVEL, static_cast<int64_t>(level::UNKNOWN));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool obsffmpeg::ui::nvenc_h264_handler::has_keyframe_support(obsffmpeg::encoder*)
|
bool nvenc_h264_handler::has_keyframe_support(ffmpeg_instance*)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::nvenc_h264_handler::get_properties(obs_properties_t* props, const AVCodec* codec,
|
void nvenc_h264_handler::get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context, bool)
|
||||||
AVCodecContext* context, bool)
|
|
||||||
{
|
{
|
||||||
if (!context) {
|
if (!context) {
|
||||||
this->get_encoder_properties(props, codec);
|
this->get_encoder_properties(props, codec);
|
||||||
|
@ -90,20 +81,19 @@ void obsffmpeg::ui::nvenc_h264_handler::get_properties(obs_properties_t* props,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::nvenc_h264_handler::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context)
|
void nvenc_h264_handler::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context)
|
||||||
{
|
{
|
||||||
nvenc::update(settings, codec, context);
|
nvenc::update(settings, codec, context);
|
||||||
|
|
||||||
{
|
{
|
||||||
auto found =
|
auto found = profiles.find(static_cast<profile>(obs_data_get_int(settings, P_H264_PROFILE)));
|
||||||
profiles.find(static_cast<codecs::h264::profile>(obs_data_get_int(settings, P_H264_PROFILE)));
|
|
||||||
if (found != profiles.end()) {
|
if (found != profiles.end()) {
|
||||||
av_opt_set(context->priv_data, "profile", found->second.c_str(), 0);
|
av_opt_set(context->priv_data, "profile", found->second.c_str(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto found = levels.find(static_cast<codecs::h264::level>(obs_data_get_int(settings, P_H264_LEVEL)));
|
auto found = levels.find(static_cast<level>(obs_data_get_int(settings, P_H264_LEVEL)));
|
||||||
if (found != levels.end()) {
|
if (found != levels.end()) {
|
||||||
av_opt_set(context->priv_data, "level", found->second.c_str(), 0);
|
av_opt_set(context->priv_data, "level", found->second.c_str(), 0);
|
||||||
} else {
|
} else {
|
||||||
|
@ -112,24 +102,24 @@ void obsffmpeg::ui::nvenc_h264_handler::update(obs_data_t* settings, const AVCod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::nvenc_h264_handler::override_update(obsffmpeg::encoder* instance, obs_data_t* settings)
|
void nvenc_h264_handler::override_update(ffmpeg_instance* instance, obs_data_t* settings)
|
||||||
{
|
{
|
||||||
nvenc::override_update(instance, settings);
|
nvenc::override_update(instance, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::nvenc_h264_handler::log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context)
|
void nvenc_h264_handler::log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context)
|
||||||
{
|
{
|
||||||
nvenc::log_options(settings, codec, context);
|
nvenc::log_options(settings, codec, context);
|
||||||
|
|
||||||
PLOG_INFO("[%s] H.265/HEVC:", codec->name);
|
LOG_INFO("[%s] H.265/HEVC:", codec->name);
|
||||||
ffmpeg::tools::print_av_option_string(context, "profile", " Profile", [](int64_t v) {
|
::ffmpeg::tools::print_av_option_string(context, "profile", " Profile", [](int64_t v) {
|
||||||
profile val = static_cast<profile>(v);
|
profile val = static_cast<profile>(v);
|
||||||
auto index = profiles.find(val);
|
auto index = profiles.find(val);
|
||||||
if (index != profiles.end())
|
if (index != profiles.end())
|
||||||
return index->second;
|
return index->second;
|
||||||
return std::string("<Unknown>");
|
return std::string("<Unknown>");
|
||||||
});
|
});
|
||||||
ffmpeg::tools::print_av_option_string(context, "level", " Level", [](int64_t v) {
|
::ffmpeg::tools::print_av_option_string(context, "level", " Level", [](int64_t v) {
|
||||||
level val = static_cast<level>(v);
|
level val = static_cast<level>(v);
|
||||||
auto index = levels.find(val);
|
auto index = levels.find(val);
|
||||||
if (index != levels.end())
|
if (index != levels.end())
|
||||||
|
@ -138,34 +128,32 @@ void obsffmpeg::ui::nvenc_h264_handler::log_options(obs_data_t* settings, const
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::nvenc_h264_handler::get_encoder_properties(obs_properties_t* props, const AVCodec* codec)
|
void nvenc_h264_handler::get_encoder_properties(obs_properties_t* props, const AVCodec* codec)
|
||||||
{
|
{
|
||||||
nvenc::get_properties_pre(props, codec);
|
nvenc::get_properties_pre(props, codec);
|
||||||
|
|
||||||
{
|
{
|
||||||
obs_properties_t* grp = props;
|
obs_properties_t* grp = props;
|
||||||
if (!obsffmpeg::are_property_groups_broken()) {
|
if (!util::are_property_groups_broken()) {
|
||||||
grp = obs_properties_create();
|
grp = obs_properties_create();
|
||||||
obs_properties_add_group(props, P_H264, TRANSLATE(P_H264), OBS_GROUP_NORMAL, grp);
|
obs_properties_add_group(props, P_H264, D_TRANSLATE(P_H264), OBS_GROUP_NORMAL, grp);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_list(grp, P_H264_PROFILE, TRANSLATE(P_H264_PROFILE),
|
auto p = obs_properties_add_list(grp, P_H264_PROFILE, D_TRANSLATE(P_H264_PROFILE), OBS_COMBO_TYPE_LIST,
|
||||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
OBS_COMBO_FORMAT_INT);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(P_H264_PROFILE)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(P_H264_PROFILE)));
|
||||||
obs_property_list_add_int(p, TRANSLATE(S_STATE_DEFAULT),
|
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), static_cast<int64_t>(profile::UNKNOWN));
|
||||||
static_cast<int64_t>(codecs::h264::profile::UNKNOWN));
|
|
||||||
for (auto const kv : profiles) {
|
for (auto const kv : profiles) {
|
||||||
std::string trans = std::string(P_H264_PROFILE) + "." + kv.second;
|
std::string trans = std::string(P_H264_PROFILE) + "." + kv.second;
|
||||||
obs_property_list_add_int(p, TRANSLATE(trans.c_str()), static_cast<int64_t>(kv.first));
|
obs_property_list_add_int(p, D_TRANSLATE(trans.c_str()), static_cast<int64_t>(kv.first));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_list(grp, P_H264_LEVEL, TRANSLATE(P_H264_LEVEL),
|
auto p = obs_properties_add_list(grp, P_H264_LEVEL, D_TRANSLATE(P_H264_LEVEL), OBS_COMBO_TYPE_LIST,
|
||||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
OBS_COMBO_FORMAT_INT);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(P_H264_LEVEL)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(P_H264_LEVEL)));
|
||||||
obs_property_list_add_int(p, TRANSLATE(S_STATE_AUTOMATIC),
|
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_AUTOMATIC), static_cast<int64_t>(level::UNKNOWN));
|
||||||
static_cast<int64_t>(codecs::h264::level::UNKNOWN));
|
|
||||||
for (auto const kv : levels) {
|
for (auto const kv : levels) {
|
||||||
obs_property_list_add_int(p, kv.second.c_str(), static_cast<int64_t>(kv.first));
|
obs_property_list_add_int(p, kv.second.c_str(), static_cast<int64_t>(kv.first));
|
||||||
}
|
}
|
||||||
|
@ -175,8 +163,7 @@ void obsffmpeg::ui::nvenc_h264_handler::get_encoder_properties(obs_properties_t*
|
||||||
nvenc::get_properties_post(props, codec);
|
nvenc::get_properties_post(props, codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::nvenc_h264_handler::get_runtime_properties(obs_properties_t* props, const AVCodec* codec,
|
void nvenc_h264_handler::get_runtime_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context)
|
||||||
AVCodecContext* context)
|
|
||||||
{
|
{
|
||||||
nvenc::get_runtime_properties(props, codec, context);
|
nvenc::get_runtime_properties(props, codec, context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,37 +30,31 @@ extern "C" {
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace obsffmpeg {
|
namespace encoder::ffmpeg::handler {
|
||||||
namespace ui {
|
class nvenc_h264_handler : public handler {
|
||||||
class nvenc_h264_handler : public handler {
|
public /*factory*/:
|
||||||
public /*factory*/:
|
virtual void adjust_encoder_info(ffmpeg_factory* factory, ffmpeg_info* main, ffmpeg_info* fallback);
|
||||||
virtual void adjust_encoder_info(obsffmpeg::encoder_factory* factory,
|
|
||||||
obsffmpeg::encoder_info* main,
|
|
||||||
obsffmpeg::encoder_info* fallback);
|
|
||||||
|
|
||||||
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context,
|
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, bool hw_encode);
|
||||||
bool hw_encode);
|
|
||||||
|
|
||||||
public /*settings*/:
|
public /*settings*/:
|
||||||
virtual bool has_keyframe_support(obsffmpeg::encoder* instance);
|
virtual bool has_keyframe_support(ffmpeg_instance* instance);
|
||||||
|
|
||||||
virtual void get_properties(obs_properties_t* props, const AVCodec* codec,
|
virtual void get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context,
|
||||||
AVCodecContext* context, bool hw_encode);
|
bool hw_encode);
|
||||||
|
|
||||||
virtual void update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
virtual void update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
||||||
|
|
||||||
virtual void override_update(obsffmpeg::encoder* instance, obs_data_t* settings);
|
virtual void override_update(ffmpeg_instance* instance, obs_data_t* settings);
|
||||||
|
|
||||||
virtual void log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
virtual void log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
||||||
|
|
||||||
public /*instance*/:
|
public /*instance*/:
|
||||||
//virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
//virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void get_encoder_properties(obs_properties_t* props, const AVCodec* codec);
|
void get_encoder_properties(obs_properties_t* props, const AVCodec* codec);
|
||||||
|
|
||||||
void get_runtime_properties(obs_properties_t* props, const AVCodec* codec,
|
void get_runtime_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context);
|
||||||
AVCodecContext* context);
|
};
|
||||||
};
|
} // namespace encoder::ffmpeg::handler
|
||||||
} // namespace ui
|
|
||||||
} // namespace obsffmpeg
|
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
|
|
||||||
#include "nvenc_hevc_handler.hpp"
|
#include "nvenc_hevc_handler.hpp"
|
||||||
#include "codecs/hevc.hpp"
|
#include "../codecs/hevc.hpp"
|
||||||
#include "encoder.hpp"
|
#include "../ffmpeg-encoder.hpp"
|
||||||
#include "ffmpeg/tools.hpp"
|
#include "ffmpeg/tools.hpp"
|
||||||
#include "nvenc_shared.hpp"
|
#include "nvenc_shared.hpp"
|
||||||
#include "plugin.hpp"
|
#include "plugin.hpp"
|
||||||
|
@ -36,56 +36,47 @@ extern "C" {
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace obsffmpeg::codecs::hevc;
|
using namespace encoder::ffmpeg::handler;
|
||||||
|
using namespace encoder::codec::hevc;
|
||||||
|
|
||||||
std::map<profile, std::string> profiles{
|
std::map<profile, std::string> profiles{
|
||||||
{profile::MAIN, "main"},
|
{profile::MAIN, "main"},
|
||||||
{profile::MAIN10, "main10"},
|
{profile::MAIN10, "main10"},
|
||||||
{profile::RANGE_EXTENDED, "rext"},
|
{profile::RANGE_EXTENDED, "rext"},
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<tier, std::string> tiers{
|
std::map<tier, std::string> tiers{
|
||||||
{tier::MAIN, "main"},
|
{tier::MAIN, "main"},
|
||||||
{tier::HIGH, "high"},
|
{tier::HIGH, "high"},
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<level, std::string> levels{
|
std::map<level, std::string> levels{
|
||||||
{level::L1_0, "1.0"}, {level::L2_0, "2.0"}, {level::L2_1, "2.1"}, {level::L3_0, "3.0"}, {level::L3_1, "3.1"},
|
{level::L1_0, "1.0"}, {level::L2_0, "2.0"}, {level::L2_1, "2.1"}, {level::L3_0, "3.0"}, {level::L3_1, "3.1"},
|
||||||
{level::L4_0, "4.0"}, {level::L4_1, "4.1"}, {level::L5_0, "5.0"}, {level::L5_1, "5.1"}, {level::L5_2, "5.2"},
|
{level::L4_0, "4.0"}, {level::L4_1, "4.1"}, {level::L5_0, "5.0"}, {level::L5_1, "5.1"}, {level::L5_2, "5.2"},
|
||||||
{level::L6_0, "6.0"}, {level::L6_1, "6.1"}, {level::L6_2, "6.2"},
|
{level::L6_0, "6.0"}, {level::L6_1, "6.1"}, {level::L6_2, "6.2"},
|
||||||
};
|
};
|
||||||
|
|
||||||
INITIALIZER(nvenc_hevc_handler_init)
|
void nvenc_hevc_handler::adjust_encoder_info(ffmpeg_factory*, ffmpeg_info* main, ffmpeg_info* fallback)
|
||||||
{
|
|
||||||
obsffmpeg::initializers.push_back([]() {
|
|
||||||
obsffmpeg::register_codec_handler("hevc_nvenc", std::make_shared<obsffmpeg::ui::nvenc_hevc_handler>());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
void obsffmpeg::ui::nvenc_hevc_handler::adjust_encoder_info(obsffmpeg::encoder_factory*, obsffmpeg::encoder_info* main,
|
|
||||||
obsffmpeg::encoder_info* fallback)
|
|
||||||
{
|
{
|
||||||
main->readable_name = "H.265/HEVC Nvidia NVENC (Hardware)";
|
main->readable_name = "H.265/HEVC Nvidia NVENC (Hardware)";
|
||||||
fallback->readable_name = "H.265/HEVC Nvidia NVENC (Software)";
|
fallback->readable_name = "H.265/HEVC Nvidia NVENC (Software)";
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::nvenc_hevc_handler::get_defaults(obs_data_t* settings, const AVCodec* codec,
|
void nvenc_hevc_handler::get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, bool)
|
||||||
AVCodecContext* context, bool)
|
|
||||||
{
|
{
|
||||||
nvenc::get_defaults(settings, codec, context);
|
nvenc::get_defaults(settings, codec, context);
|
||||||
|
|
||||||
obs_data_set_default_int(settings, P_HEVC_PROFILE, static_cast<int64_t>(codecs::hevc::profile::MAIN));
|
obs_data_set_default_int(settings, P_HEVC_PROFILE, static_cast<int64_t>(profile::MAIN));
|
||||||
obs_data_set_default_int(settings, P_HEVC_TIER, static_cast<int64_t>(codecs::hevc::profile::MAIN));
|
obs_data_set_default_int(settings, P_HEVC_TIER, static_cast<int64_t>(profile::MAIN));
|
||||||
obs_data_set_default_int(settings, P_HEVC_LEVEL, static_cast<int64_t>(codecs::hevc::level::UNKNOWN));
|
obs_data_set_default_int(settings, P_HEVC_LEVEL, static_cast<int64_t>(level::UNKNOWN));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool obsffmpeg::ui::nvenc_hevc_handler::has_keyframe_support(obsffmpeg::encoder*)
|
bool nvenc_hevc_handler::has_keyframe_support(ffmpeg_instance*)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::nvenc_hevc_handler::get_properties(obs_properties_t* props, const AVCodec* codec,
|
void nvenc_hevc_handler::get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context, bool)
|
||||||
AVCodecContext* context, bool)
|
|
||||||
{
|
{
|
||||||
if (!context) {
|
if (!context) {
|
||||||
this->get_encoder_properties(props, codec);
|
this->get_encoder_properties(props, codec);
|
||||||
|
@ -94,7 +85,7 @@ void obsffmpeg::ui::nvenc_hevc_handler::get_properties(obs_properties_t* props,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::nvenc_hevc_handler::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context)
|
void nvenc_hevc_handler::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context)
|
||||||
{
|
{
|
||||||
nvenc::update(settings, codec, context);
|
nvenc::update(settings, codec, context);
|
||||||
|
|
||||||
|
@ -120,31 +111,31 @@ void obsffmpeg::ui::nvenc_hevc_handler::update(obs_data_t* settings, const AVCod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::nvenc_hevc_handler::override_update(obsffmpeg::encoder* instance, obs_data_t* settings)
|
void nvenc_hevc_handler::override_update(ffmpeg_instance* instance, obs_data_t* settings)
|
||||||
{
|
{
|
||||||
nvenc::override_update(instance, settings);
|
nvenc::override_update(instance, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::nvenc_hevc_handler::log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context)
|
void nvenc_hevc_handler::log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context)
|
||||||
{
|
{
|
||||||
nvenc::log_options(settings, codec, context);
|
nvenc::log_options(settings, codec, context);
|
||||||
|
|
||||||
PLOG_INFO("[%s] H.265/HEVC:", codec->name);
|
LOG_INFO("[%s] H.265/HEVC:", codec->name);
|
||||||
ffmpeg::tools::print_av_option_string(context, "profile", " Profile", [](int64_t v) {
|
::ffmpeg::tools::print_av_option_string(context, "profile", " Profile", [](int64_t v) {
|
||||||
profile val = static_cast<profile>(v);
|
profile val = static_cast<profile>(v);
|
||||||
auto index = profiles.find(val);
|
auto index = profiles.find(val);
|
||||||
if (index != profiles.end())
|
if (index != profiles.end())
|
||||||
return index->second;
|
return index->second;
|
||||||
return std::string("<Unknown>");
|
return std::string("<Unknown>");
|
||||||
});
|
});
|
||||||
ffmpeg::tools::print_av_option_string(context, "level", " Level", [](int64_t v) {
|
::ffmpeg::tools::print_av_option_string(context, "level", " Level", [](int64_t v) {
|
||||||
level val = static_cast<level>(v);
|
level val = static_cast<level>(v);
|
||||||
auto index = levels.find(val);
|
auto index = levels.find(val);
|
||||||
if (index != levels.end())
|
if (index != levels.end())
|
||||||
return index->second;
|
return index->second;
|
||||||
return std::string("<Unknown>");
|
return std::string("<Unknown>");
|
||||||
});
|
});
|
||||||
ffmpeg::tools::print_av_option_string(context, "tier", " Tier", [](int64_t v) {
|
::ffmpeg::tools::print_av_option_string(context, "tier", " Tier", [](int64_t v) {
|
||||||
tier val = static_cast<tier>(v);
|
tier val = static_cast<tier>(v);
|
||||||
auto index = tiers.find(val);
|
auto index = tiers.find(val);
|
||||||
if (index != tiers.end())
|
if (index != tiers.end())
|
||||||
|
@ -153,45 +144,42 @@ void obsffmpeg::ui::nvenc_hevc_handler::log_options(obs_data_t* settings, const
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::nvenc_hevc_handler::get_encoder_properties(obs_properties_t* props, const AVCodec* codec)
|
void nvenc_hevc_handler::get_encoder_properties(obs_properties_t* props, const AVCodec* codec)
|
||||||
{
|
{
|
||||||
nvenc::get_properties_pre(props, codec);
|
nvenc::get_properties_pre(props, codec);
|
||||||
|
|
||||||
{
|
{
|
||||||
obs_properties_t* grp = props;
|
obs_properties_t* grp = props;
|
||||||
if (!obsffmpeg::are_property_groups_broken()) {
|
if (!util::are_property_groups_broken()) {
|
||||||
grp = obs_properties_create();
|
grp = obs_properties_create();
|
||||||
obs_properties_add_group(props, P_HEVC, TRANSLATE(P_HEVC), OBS_GROUP_NORMAL, grp);
|
obs_properties_add_group(props, P_HEVC, D_TRANSLATE(P_HEVC), OBS_GROUP_NORMAL, grp);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_list(grp, P_HEVC_PROFILE, TRANSLATE(P_HEVC_PROFILE),
|
auto p = obs_properties_add_list(grp, P_HEVC_PROFILE, D_TRANSLATE(P_HEVC_PROFILE), OBS_COMBO_TYPE_LIST,
|
||||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
OBS_COMBO_FORMAT_INT);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(P_HEVC_PROFILE)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(P_HEVC_PROFILE)));
|
||||||
obs_property_list_add_int(p, TRANSLATE(S_STATE_DEFAULT),
|
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), static_cast<int64_t>(profile::UNKNOWN));
|
||||||
static_cast<int64_t>(codecs::hevc::profile::UNKNOWN));
|
|
||||||
for (auto const kv : profiles) {
|
for (auto const kv : profiles) {
|
||||||
std::string trans = std::string(P_HEVC_PROFILE) + "." + kv.second;
|
std::string trans = std::string(P_HEVC_PROFILE) + "." + kv.second;
|
||||||
obs_property_list_add_int(p, TRANSLATE(trans.c_str()), static_cast<int64_t>(kv.first));
|
obs_property_list_add_int(p, D_TRANSLATE(trans.c_str()), static_cast<int64_t>(kv.first));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_list(grp, P_HEVC_TIER, TRANSLATE(P_HEVC_TIER), OBS_COMBO_TYPE_LIST,
|
auto p = obs_properties_add_list(grp, P_HEVC_TIER, D_TRANSLATE(P_HEVC_TIER), OBS_COMBO_TYPE_LIST,
|
||||||
OBS_COMBO_FORMAT_INT);
|
OBS_COMBO_FORMAT_INT);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(P_HEVC_TIER)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(P_HEVC_TIER)));
|
||||||
obs_property_list_add_int(p, TRANSLATE(S_STATE_DEFAULT),
|
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), static_cast<int64_t>(tier::UNKNOWN));
|
||||||
static_cast<int64_t>(codecs::hevc::tier::UNKNOWN));
|
|
||||||
for (auto const kv : tiers) {
|
for (auto const kv : tiers) {
|
||||||
std::string trans = std::string(P_HEVC_TIER) + "." + kv.second;
|
std::string trans = std::string(P_HEVC_TIER) + "." + kv.second;
|
||||||
obs_property_list_add_int(p, TRANSLATE(trans.c_str()), static_cast<int64_t>(kv.first));
|
obs_property_list_add_int(p, D_TRANSLATE(trans.c_str()), static_cast<int64_t>(kv.first));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_list(grp, P_HEVC_LEVEL, TRANSLATE(P_HEVC_LEVEL),
|
auto p = obs_properties_add_list(grp, P_HEVC_LEVEL, D_TRANSLATE(P_HEVC_LEVEL), OBS_COMBO_TYPE_LIST,
|
||||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
OBS_COMBO_FORMAT_INT);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(P_HEVC_LEVEL)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(P_HEVC_LEVEL)));
|
||||||
obs_property_list_add_int(p, TRANSLATE(S_STATE_AUTOMATIC),
|
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_AUTOMATIC), static_cast<int64_t>(level::UNKNOWN));
|
||||||
static_cast<int64_t>(codecs::hevc::level::UNKNOWN));
|
|
||||||
for (auto const kv : levels) {
|
for (auto const kv : levels) {
|
||||||
obs_property_list_add_int(p, kv.second.c_str(), static_cast<int64_t>(kv.first));
|
obs_property_list_add_int(p, kv.second.c_str(), static_cast<int64_t>(kv.first));
|
||||||
}
|
}
|
||||||
|
@ -201,8 +189,7 @@ void obsffmpeg::ui::nvenc_hevc_handler::get_encoder_properties(obs_properties_t*
|
||||||
nvenc::get_properties_post(props, codec);
|
nvenc::get_properties_post(props, codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::nvenc_hevc_handler::get_runtime_properties(obs_properties_t* props, const AVCodec* codec,
|
void nvenc_hevc_handler::get_runtime_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context)
|
||||||
AVCodecContext* context)
|
|
||||||
{
|
{
|
||||||
nvenc::get_runtime_properties(props, codec, context);
|
nvenc::get_runtime_properties(props, codec, context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,37 +30,31 @@ extern "C" {
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace obsffmpeg {
|
namespace encoder::ffmpeg::handler {
|
||||||
namespace ui {
|
class nvenc_hevc_handler : public handler {
|
||||||
class nvenc_hevc_handler : public handler {
|
public /*factory*/:
|
||||||
public /*factory*/:
|
virtual void adjust_encoder_info(ffmpeg_factory* factory, ffmpeg_info* main, ffmpeg_info* fallback);
|
||||||
virtual void adjust_encoder_info(obsffmpeg::encoder_factory* factory,
|
|
||||||
obsffmpeg::encoder_info* main,
|
|
||||||
obsffmpeg::encoder_info* fallback);
|
|
||||||
|
|
||||||
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context,
|
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, bool hw_encode);
|
||||||
bool hw_encode);
|
|
||||||
|
|
||||||
public /*settings*/:
|
public /*settings*/:
|
||||||
virtual bool has_keyframe_support(obsffmpeg::encoder* instance);
|
virtual bool has_keyframe_support(ffmpeg_instance* instance);
|
||||||
|
|
||||||
virtual void get_properties(obs_properties_t* props, const AVCodec* codec,
|
virtual void get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context,
|
||||||
AVCodecContext* context, bool hw_encode);
|
bool hw_encode);
|
||||||
|
|
||||||
virtual void update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
virtual void update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
||||||
|
|
||||||
virtual void override_update(obsffmpeg::encoder* instance, obs_data_t* settings);
|
virtual void override_update(ffmpeg_instance* instance, obs_data_t* settings);
|
||||||
|
|
||||||
virtual void log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
virtual void log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
||||||
|
|
||||||
public /*instance*/:
|
public /*instance*/:
|
||||||
//virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
//virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void get_encoder_properties(obs_properties_t* props, const AVCodec* codec);
|
void get_encoder_properties(obs_properties_t* props, const AVCodec* codec);
|
||||||
|
|
||||||
void get_runtime_properties(obs_properties_t* props, const AVCodec* codec,
|
void get_runtime_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context);
|
||||||
AVCodecContext* context);
|
};
|
||||||
};
|
} // namespace encoder::ffmpeg::handler
|
||||||
} // namespace ui
|
|
||||||
} // namespace obsffmpeg
|
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
|
|
||||||
#include "nvenc_shared.hpp"
|
#include "nvenc_shared.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "codecs/hevc.hpp"
|
#include "../codecs/hevc.hpp"
|
||||||
#include "encoder.hpp"
|
#include "../ffmpeg-encoder.hpp"
|
||||||
#include "ffmpeg/tools.hpp"
|
#include "ffmpeg/tools.hpp"
|
||||||
#include "plugin.hpp"
|
#include "plugin.hpp"
|
||||||
#include "strings.hpp"
|
#include "strings.hpp"
|
||||||
|
@ -76,65 +76,67 @@ extern "C" {
|
||||||
#define ST_OTHER_WEIGHTED_PREDICTION ST_OTHER ".WeightedPrediction"
|
#define ST_OTHER_WEIGHTED_PREDICTION ST_OTHER ".WeightedPrediction"
|
||||||
#define ST_OTHER_NONREFERENCE_PFRAMES ST_OTHER ".NonReferencePFrames"
|
#define ST_OTHER_NONREFERENCE_PFRAMES ST_OTHER ".NonReferencePFrames"
|
||||||
|
|
||||||
using namespace obsffmpeg::nvenc;
|
using namespace encoder::ffmpeg::handler;
|
||||||
|
using namespace ffmpeg;
|
||||||
|
|
||||||
std::map<preset, std::string> obsffmpeg::nvenc::presets{
|
std::map<nvenc::preset, std::string> nvenc::presets{
|
||||||
{preset::DEFAULT, ST_PRESET_(Default)},
|
{nvenc::preset::DEFAULT, ST_PRESET_(Default)},
|
||||||
{preset::SLOW, ST_PRESET_(Slow)},
|
{nvenc::preset::SLOW, ST_PRESET_(Slow)},
|
||||||
{preset::MEDIUM, ST_PRESET_(Medium)},
|
{nvenc::preset::MEDIUM, ST_PRESET_(Medium)},
|
||||||
{preset::FAST, ST_PRESET_(Fast)},
|
{nvenc::preset::FAST, ST_PRESET_(Fast)},
|
||||||
{preset::HIGH_PERFORMANCE, ST_PRESET_(HighPerformance)},
|
{nvenc::preset::HIGH_PERFORMANCE, ST_PRESET_(HighPerformance)},
|
||||||
{preset::HIGH_QUALITY, ST_PRESET_(HighQuality)},
|
{nvenc::preset::HIGH_QUALITY, ST_PRESET_(HighQuality)},
|
||||||
{preset::BLURAYDISC, ST_PRESET_(BluRayDisc)},
|
{nvenc::preset::BLURAYDISC, ST_PRESET_(BluRayDisc)},
|
||||||
{preset::LOW_LATENCY, ST_PRESET_(LowLatency)},
|
{nvenc::preset::LOW_LATENCY, ST_PRESET_(LowLatency)},
|
||||||
{preset::LOW_LATENCY_HIGH_PERFORMANCE, ST_PRESET_(LowLatencyHighPerformance)},
|
{nvenc::preset::LOW_LATENCY_HIGH_PERFORMANCE, ST_PRESET_(LowLatencyHighPerformance)},
|
||||||
{preset::LOW_LATENCY_HIGH_QUALITY, ST_PRESET_(LowLatencyHighQuality)},
|
{nvenc::preset::LOW_LATENCY_HIGH_QUALITY, ST_PRESET_(LowLatencyHighQuality)},
|
||||||
{preset::LOSSLESS, ST_PRESET_(Lossless)},
|
{nvenc::preset::LOSSLESS, ST_PRESET_(Lossless)},
|
||||||
{preset::LOSSLESS_HIGH_PERFORMANCE, ST_PRESET_(LosslessHighPerformance)},
|
{nvenc::preset::LOSSLESS_HIGH_PERFORMANCE, ST_PRESET_(LosslessHighPerformance)},
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<preset, std::string> obsffmpeg::nvenc::preset_to_opt{
|
std::map<nvenc::preset, std::string> nvenc::preset_to_opt{
|
||||||
{preset::DEFAULT, "default"},
|
{nvenc::preset::DEFAULT, "default"},
|
||||||
{preset::SLOW, "slow"},
|
{nvenc::preset::SLOW, "slow"},
|
||||||
{preset::MEDIUM, "medium"},
|
{nvenc::preset::MEDIUM, "medium"},
|
||||||
{preset::FAST, "fast"},
|
{nvenc::preset::FAST, "fast"},
|
||||||
{preset::HIGH_PERFORMANCE, "hp"},
|
{nvenc::preset::HIGH_PERFORMANCE, "hp"},
|
||||||
{preset::HIGH_QUALITY, "hq"},
|
{nvenc::preset::HIGH_QUALITY, "hq"},
|
||||||
{preset::BLURAYDISC, "bd"},
|
{nvenc::preset::BLURAYDISC, "bd"},
|
||||||
{preset::LOW_LATENCY, "ll"},
|
{nvenc::preset::LOW_LATENCY, "ll"},
|
||||||
{preset::LOW_LATENCY_HIGH_PERFORMANCE, "llhp"},
|
{nvenc::preset::LOW_LATENCY_HIGH_PERFORMANCE, "llhp"},
|
||||||
{preset::LOW_LATENCY_HIGH_QUALITY, "llhq"},
|
{nvenc::preset::LOW_LATENCY_HIGH_QUALITY, "llhq"},
|
||||||
{preset::LOSSLESS, "lossless"},
|
{nvenc::preset::LOSSLESS, "lossless"},
|
||||||
{preset::LOSSLESS_HIGH_PERFORMANCE, "losslesshp"},
|
{nvenc::preset::LOSSLESS_HIGH_PERFORMANCE, "losslesshp"},
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<ratecontrolmode, std::string> obsffmpeg::nvenc::ratecontrolmodes{
|
std::map<nvenc::ratecontrolmode, std::string> nvenc::ratecontrolmodes{
|
||||||
{ratecontrolmode::CQP, ST_RATECONTROL_MODE_(CQP)},
|
{nvenc::ratecontrolmode::CQP, ST_RATECONTROL_MODE_(CQP)},
|
||||||
{ratecontrolmode::VBR, ST_RATECONTROL_MODE_(VBR)},
|
{nvenc::ratecontrolmode::VBR, ST_RATECONTROL_MODE_(VBR)},
|
||||||
{ratecontrolmode::VBR_HQ, ST_RATECONTROL_MODE_(VBR_HQ)},
|
{nvenc::ratecontrolmode::VBR_HQ, ST_RATECONTROL_MODE_(VBR_HQ)},
|
||||||
{ratecontrolmode::CBR, ST_RATECONTROL_MODE_(CBR)},
|
{nvenc::ratecontrolmode::CBR, ST_RATECONTROL_MODE_(CBR)},
|
||||||
{ratecontrolmode::CBR_HQ, ST_RATECONTROL_MODE_(CBR_HQ)},
|
{nvenc::ratecontrolmode::CBR_HQ, ST_RATECONTROL_MODE_(CBR_HQ)},
|
||||||
{ratecontrolmode::CBR_LD_HQ, ST_RATECONTROL_MODE_(CBR_LD_HQ)},
|
{nvenc::ratecontrolmode::CBR_LD_HQ, ST_RATECONTROL_MODE_(CBR_LD_HQ)},
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<ratecontrolmode, std::string> obsffmpeg::nvenc::ratecontrolmode_to_opt{
|
std::map<nvenc::ratecontrolmode, std::string> nvenc::ratecontrolmode_to_opt{
|
||||||
{ratecontrolmode::CQP, "constqp"}, {ratecontrolmode::VBR, "vbr"}, {ratecontrolmode::VBR_HQ, "vbr_hq"},
|
{nvenc::ratecontrolmode::CQP, "constqp"}, {nvenc::ratecontrolmode::VBR, "vbr"},
|
||||||
{ratecontrolmode::CBR, "cbr"}, {ratecontrolmode::CBR_HQ, "cbr_hq"}, {ratecontrolmode::CBR_LD_HQ, "cbr_ld_hq"},
|
{nvenc::ratecontrolmode::VBR_HQ, "vbr_hq"}, {nvenc::ratecontrolmode::CBR, "cbr"},
|
||||||
|
{nvenc::ratecontrolmode::CBR_HQ, "cbr_hq"}, {nvenc::ratecontrolmode::CBR_LD_HQ, "cbr_ld_hq"},
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<b_ref_mode, std::string> obsffmpeg::nvenc::b_ref_modes{
|
std::map<nvenc::b_ref_mode, std::string> nvenc::b_ref_modes{
|
||||||
{b_ref_mode::DISABLED, S_STATE_DISABLED},
|
{nvenc::b_ref_mode::DISABLED, S_STATE_DISABLED},
|
||||||
{b_ref_mode::EACH, ST_OTHER_BFRAME_REFERENCEMODE ".Each"},
|
{nvenc::b_ref_mode::EACH, ST_OTHER_BFRAME_REFERENCEMODE ".Each"},
|
||||||
{b_ref_mode::MIDDLE, ST_OTHER_BFRAME_REFERENCEMODE ".Middle"},
|
{nvenc::b_ref_mode::MIDDLE, ST_OTHER_BFRAME_REFERENCEMODE ".Middle"},
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<b_ref_mode, std::string> obsffmpeg::nvenc::b_ref_mode_to_opt{
|
std::map<nvenc::b_ref_mode, std::string> nvenc::b_ref_mode_to_opt{
|
||||||
{b_ref_mode::DISABLED, "disabled"},
|
{nvenc::b_ref_mode::DISABLED, "disabled"},
|
||||||
{b_ref_mode::EACH, "each"},
|
{nvenc::b_ref_mode::EACH, "each"},
|
||||||
{b_ref_mode::MIDDLE, "middle"},
|
{nvenc::b_ref_mode::MIDDLE, "middle"},
|
||||||
};
|
};
|
||||||
|
|
||||||
void obsffmpeg::nvenc::override_update(obsffmpeg::encoder* instance, obs_data_t*)
|
void nvenc::override_update(ffmpeg_instance* instance, obs_data_t*)
|
||||||
{
|
{
|
||||||
AVCodecContext* context = const_cast<AVCodecContext*>(instance->get_avcodeccontext());
|
AVCodecContext* context = const_cast<AVCodecContext*>(instance->get_avcodeccontext());
|
||||||
|
|
||||||
|
@ -164,9 +166,9 @@ void obsffmpeg::nvenc::override_update(obsffmpeg::encoder* instance, obs_data_t*
|
||||||
context->delay = static_cast<int>(std::min(std::max(async_depth, 3ll), surfaces - 1));
|
context->delay = static_cast<int>(std::min(std::max(async_depth, 3ll), surfaces - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::nvenc::get_defaults(obs_data_t* settings, const AVCodec*, AVCodecContext*)
|
void nvenc::get_defaults(obs_data_t* settings, const AVCodec*, AVCodecContext*)
|
||||||
{
|
{
|
||||||
obs_data_set_default_int(settings, ST_PRESET, static_cast<int64_t>(preset::DEFAULT));
|
obs_data_set_default_int(settings, ST_PRESET, static_cast<int64_t>(nvenc::preset::DEFAULT));
|
||||||
|
|
||||||
obs_data_set_default_int(settings, ST_RATECONTROL_MODE, static_cast<int64_t>(ratecontrolmode::CBR_HQ));
|
obs_data_set_default_int(settings, ST_RATECONTROL_MODE, static_cast<int64_t>(ratecontrolmode::CBR_HQ));
|
||||||
obs_data_set_default_int(settings, ST_RATECONTROL_TWOPASS, -1);
|
obs_data_set_default_int(settings, ST_RATECONTROL_TWOPASS, -1);
|
||||||
|
@ -203,28 +205,27 @@ void obsffmpeg::nvenc::get_defaults(obs_data_t* settings, const AVCodec*, AVCode
|
||||||
obs_data_set_default_int(settings, "bitrate", 0);
|
obs_data_set_default_int(settings, "bitrate", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool modified_ratecontrol(obs_properties_t* props, obs_property_t*, obs_data_t* settings)
|
static bool modified_ratecontrol(obs_properties_t* props, obs_property_t*, obs_data_t* settings) noexcept
|
||||||
{
|
{
|
||||||
using namespace obsffmpeg::nvenc;
|
|
||||||
|
|
||||||
bool have_bitrate = false;
|
bool have_bitrate = false;
|
||||||
bool have_bitrate_max = false;
|
bool have_bitrate_max = false;
|
||||||
bool have_quality = false;
|
bool have_quality = false;
|
||||||
bool have_qp = false;
|
bool have_qp = false;
|
||||||
bool have_qp_init = false;
|
bool have_qp_init = false;
|
||||||
|
|
||||||
ratecontrolmode rc = static_cast<ratecontrolmode>(obs_data_get_int(settings, ST_RATECONTROL_MODE));
|
nvenc::ratecontrolmode rc = static_cast<nvenc::ratecontrolmode>(obs_data_get_int(settings, ST_RATECONTROL_MODE));
|
||||||
switch (rc) {
|
switch (rc) {
|
||||||
case ratecontrolmode::CQP:
|
case nvenc::ratecontrolmode::CQP:
|
||||||
have_qp = true;
|
have_qp = true;
|
||||||
break;
|
break;
|
||||||
case ratecontrolmode::CBR:
|
case nvenc::ratecontrolmode::INVALID:
|
||||||
case ratecontrolmode::CBR_HQ:
|
case nvenc::ratecontrolmode::CBR:
|
||||||
case ratecontrolmode::CBR_LD_HQ:
|
case nvenc::ratecontrolmode::CBR_HQ:
|
||||||
|
case nvenc::ratecontrolmode::CBR_LD_HQ:
|
||||||
have_bitrate = true;
|
have_bitrate = true;
|
||||||
break;
|
break;
|
||||||
case ratecontrolmode::VBR:
|
case nvenc::ratecontrolmode::VBR:
|
||||||
case ratecontrolmode::VBR_HQ:
|
case nvenc::ratecontrolmode::VBR_HQ:
|
||||||
have_bitrate = true;
|
have_bitrate = true;
|
||||||
have_bitrate_max = true;
|
have_bitrate_max = true;
|
||||||
have_quality = true;
|
have_quality = true;
|
||||||
|
@ -253,7 +254,7 @@ static bool modified_ratecontrol(obs_properties_t* props, obs_property_t*, obs_d
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool modified_quality(obs_properties_t* props, obs_property_t*, obs_data_t* settings)
|
static bool modified_quality(obs_properties_t* props, obs_property_t*, obs_data_t* settings) noexcept
|
||||||
{
|
{
|
||||||
bool enabled = obs_data_get_bool(settings, ST_RATECONTROL_QUALITY);
|
bool enabled = obs_data_get_bool(settings, ST_RATECONTROL_QUALITY);
|
||||||
obs_property_set_enabled(obs_properties_get(props, ST_RATECONTROL_QUALITY_MINIMUM), enabled);
|
obs_property_set_enabled(obs_properties_get(props, ST_RATECONTROL_QUALITY_MINIMUM), enabled);
|
||||||
|
@ -261,242 +262,234 @@ static bool modified_quality(obs_properties_t* props, obs_property_t*, obs_data_
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool modified_aq(obs_properties_t* props, obs_property_t*, obs_data_t* settings)
|
static bool modified_aq(obs_properties_t* props, obs_property_t*, obs_data_t* settings) noexcept
|
||||||
{
|
{
|
||||||
bool spatial_aq = obs_data_get_int(settings, ST_AQ_SPATIAL) == 1;
|
bool spatial_aq = obs_data_get_int(settings, ST_AQ_SPATIAL) == 1;
|
||||||
obs_property_set_visible(obs_properties_get(props, ST_AQ_STRENGTH), spatial_aq);
|
obs_property_set_visible(obs_properties_get(props, ST_AQ_STRENGTH), spatial_aq);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::nvenc::get_properties_pre(obs_properties_t* props, const AVCodec*)
|
void nvenc::get_properties_pre(obs_properties_t* props, const AVCodec*)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_list(props, ST_PRESET, TRANSLATE(ST_PRESET), OBS_COMBO_TYPE_LIST,
|
auto p = obs_properties_add_list(props, ST_PRESET, D_TRANSLATE(ST_PRESET), OBS_COMBO_TYPE_LIST,
|
||||||
OBS_COMBO_FORMAT_INT);
|
OBS_COMBO_FORMAT_INT);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_PRESET)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_PRESET)));
|
||||||
for (auto kv : presets) {
|
for (auto kv : presets) {
|
||||||
obs_property_list_add_int(p, TRANSLATE(kv.second.c_str()), static_cast<int64_t>(kv.first));
|
obs_property_list_add_int(p, D_TRANSLATE(kv.second.c_str()), static_cast<int64_t>(kv.first));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::nvenc::get_properties_post(obs_properties_t* props, const AVCodec* codec)
|
void nvenc::get_properties_post(obs_properties_t* props, const AVCodec* codec)
|
||||||
{
|
{
|
||||||
{ // Rate Control
|
{ // Rate Control
|
||||||
obs_properties_t* grp = props;
|
obs_properties_t* grp = props;
|
||||||
if (!obsffmpeg::are_property_groups_broken()) {
|
if (!util::are_property_groups_broken()) {
|
||||||
grp = obs_properties_create();
|
grp = obs_properties_create();
|
||||||
obs_properties_add_group(props, ST_RATECONTROL, TRANSLATE(ST_RATECONTROL), OBS_GROUP_NORMAL,
|
obs_properties_add_group(props, ST_RATECONTROL, D_TRANSLATE(ST_RATECONTROL), OBS_GROUP_NORMAL, grp);
|
||||||
grp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_list(grp, ST_RATECONTROL_MODE, TRANSLATE(ST_RATECONTROL_MODE),
|
auto p = obs_properties_add_list(grp, ST_RATECONTROL_MODE, D_TRANSLATE(ST_RATECONTROL_MODE),
|
||||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_MODE)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_MODE)));
|
||||||
obs_property_set_modified_callback(p, modified_ratecontrol);
|
obs_property_set_modified_callback(p, modified_ratecontrol);
|
||||||
for (auto kv : ratecontrolmodes) {
|
for (auto kv : ratecontrolmodes) {
|
||||||
obs_property_list_add_int(p, TRANSLATE(kv.second.c_str()),
|
obs_property_list_add_int(p, D_TRANSLATE(kv.second.c_str()), static_cast<int64_t>(kv.first));
|
||||||
static_cast<int64_t>(kv.first));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_RATECONTROL_TWOPASS,
|
auto p =
|
||||||
TRANSLATE(ST_RATECONTROL_TWOPASS));
|
util::obs_properties_add_tristate(grp, ST_RATECONTROL_TWOPASS, D_TRANSLATE(ST_RATECONTROL_TWOPASS));
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_TWOPASS)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_TWOPASS)));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_LOOKAHEAD,
|
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_LOOKAHEAD, D_TRANSLATE(ST_RATECONTROL_LOOKAHEAD),
|
||||||
TRANSLATE(ST_RATECONTROL_LOOKAHEAD), 0, 32, 1);
|
0, 32, 1);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_LOOKAHEAD)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_LOOKAHEAD)));
|
||||||
obs_property_int_set_suffix(p, " frames");
|
obs_property_int_set_suffix(p, " frames");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_RATECONTROL_ADAPTIVEI,
|
auto p =
|
||||||
TRANSLATE(ST_RATECONTROL_ADAPTIVEI));
|
util::obs_properties_add_tristate(grp, ST_RATECONTROL_ADAPTIVEI, D_TRANSLATE(ST_RATECONTROL_ADAPTIVEI));
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_ADAPTIVEI)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_ADAPTIVEI)));
|
||||||
}
|
}
|
||||||
if (strcmp(codec->name, "h264_nvenc") == 0) {
|
if (strcmp(codec->name, "h264_nvenc") == 0) {
|
||||||
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_RATECONTROL_ADAPTIVEB,
|
auto p =
|
||||||
TRANSLATE(ST_RATECONTROL_ADAPTIVEB));
|
util::obs_properties_add_tristate(grp, ST_RATECONTROL_ADAPTIVEB, D_TRANSLATE(ST_RATECONTROL_ADAPTIVEB));
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_ADAPTIVEB)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_ADAPTIVEB)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
obs_properties_t* grp = props;
|
obs_properties_t* grp = props;
|
||||||
if (!obsffmpeg::are_property_groups_broken()) {
|
if (!util::are_property_groups_broken()) {
|
||||||
grp = obs_properties_create();
|
grp = obs_properties_create();
|
||||||
obs_properties_add_group(props, ST_RATECONTROL_BITRATE, TRANSLATE(ST_RATECONTROL_BITRATE),
|
obs_properties_add_group(props, ST_RATECONTROL_BITRATE, D_TRANSLATE(ST_RATECONTROL_BITRATE),
|
||||||
OBS_GROUP_NORMAL, grp);
|
OBS_GROUP_NORMAL, grp);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_int(grp, ST_RATECONTROL_BITRATE_TARGET,
|
auto p =
|
||||||
TRANSLATE(ST_RATECONTROL_BITRATE_TARGET), 1,
|
obs_properties_add_int(grp, ST_RATECONTROL_BITRATE_TARGET, D_TRANSLATE(ST_RATECONTROL_BITRATE_TARGET),
|
||||||
std::numeric_limits<int32_t>::max(), 1);
|
1, std::numeric_limits<int32_t>::max(), 1);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_BITRATE_TARGET)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_BITRATE_TARGET)));
|
||||||
obs_property_int_set_suffix(p, " kbit/s");
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto p = obs_properties_add_int(grp, ST_RATECONTROL_BITRATE_MAXIMUM,
|
|
||||||
TRANSLATE(ST_RATECONTROL_BITRATE_MAXIMUM), 0,
|
|
||||||
std::numeric_limits<int32_t>::max(), 1);
|
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_BITRATE_MAXIMUM)));
|
|
||||||
obs_property_int_set_suffix(p, " kbit/s");
|
obs_property_int_set_suffix(p, " kbit/s");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto p =
|
auto p =
|
||||||
obs_properties_add_int(grp, S_RATECONTROL_BUFFERSIZE, TRANSLATE(S_RATECONTROL_BUFFERSIZE),
|
obs_properties_add_int(grp, ST_RATECONTROL_BITRATE_MAXIMUM, D_TRANSLATE(ST_RATECONTROL_BITRATE_MAXIMUM),
|
||||||
0, std::numeric_limits<int32_t>::max(), 1);
|
0, std::numeric_limits<int32_t>::max(), 1);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(S_RATECONTROL_BUFFERSIZE)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_BITRATE_MAXIMUM)));
|
||||||
|
obs_property_int_set_suffix(p, " kbit/s");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto p = obs_properties_add_int(grp, S_RATECONTROL_BUFFERSIZE, D_TRANSLATE(S_RATECONTROL_BUFFERSIZE), 0,
|
||||||
|
std::numeric_limits<int32_t>::max(), 1);
|
||||||
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(S_RATECONTROL_BUFFERSIZE)));
|
||||||
obs_property_int_set_suffix(p, " kbit");
|
obs_property_int_set_suffix(p, " kbit");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
obs_properties_t* grp = props;
|
obs_properties_t* grp = props;
|
||||||
if (!obsffmpeg::are_property_groups_broken()) {
|
if (!util::are_property_groups_broken()) {
|
||||||
grp = obs_properties_create();
|
grp = obs_properties_create();
|
||||||
auto p = obs_properties_add_group(props, ST_RATECONTROL_QUALITY,
|
auto p = obs_properties_add_group(props, ST_RATECONTROL_QUALITY, D_TRANSLATE(ST_RATECONTROL_QUALITY),
|
||||||
TRANSLATE(ST_RATECONTROL_QUALITY), OBS_GROUP_CHECKABLE, grp);
|
OBS_GROUP_CHECKABLE, grp);
|
||||||
obs_property_set_modified_callback(p, modified_quality);
|
obs_property_set_modified_callback(p, modified_quality);
|
||||||
} else {
|
} else {
|
||||||
auto p =
|
auto p = obs_properties_add_bool(props, ST_RATECONTROL_QUALITY, D_TRANSLATE(ST_RATECONTROL_QUALITY));
|
||||||
obs_properties_add_bool(props, ST_RATECONTROL_QUALITY, TRANSLATE(ST_RATECONTROL_QUALITY));
|
|
||||||
obs_property_set_modified_callback(p, modified_quality);
|
obs_property_set_modified_callback(p, modified_quality);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_QUALITY_MINIMUM,
|
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_QUALITY_MINIMUM,
|
||||||
TRANSLATE(ST_RATECONTROL_QUALITY_MINIMUM), 0, 51, 1);
|
D_TRANSLATE(ST_RATECONTROL_QUALITY_MINIMUM), 0, 51, 1);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_QUALITY_MINIMUM)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_QUALITY_MINIMUM)));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_QUALITY_MAXIMUM,
|
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_QUALITY_MAXIMUM,
|
||||||
TRANSLATE(ST_RATECONTROL_QUALITY_MAXIMUM), -1, 51, 1);
|
D_TRANSLATE(ST_RATECONTROL_QUALITY_MAXIMUM), -1, 51, 1);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_QUALITY_MAXIMUM)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_QUALITY_MAXIMUM)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_float_slider(props, ST_RATECONTROL_QUALITY_TARGET,
|
auto p = obs_properties_add_float_slider(props, ST_RATECONTROL_QUALITY_TARGET,
|
||||||
TRANSLATE(ST_RATECONTROL_QUALITY_TARGET), 0, 100, 0.01);
|
D_TRANSLATE(ST_RATECONTROL_QUALITY_TARGET), 0, 100, 0.01);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_QUALITY_TARGET)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_QUALITY_TARGET)));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
obs_properties_t* grp = props;
|
obs_properties_t* grp = props;
|
||||||
if (!obsffmpeg::are_property_groups_broken()) {
|
if (!util::are_property_groups_broken()) {
|
||||||
grp = obs_properties_create();
|
grp = obs_properties_create();
|
||||||
auto p = obs_properties_add_group(props, ST_RATECONTROL_QP, TRANSLATE(ST_RATECONTROL_QP),
|
auto p = obs_properties_add_group(props, ST_RATECONTROL_QP, D_TRANSLATE(ST_RATECONTROL_QP),
|
||||||
OBS_GROUP_CHECKABLE, grp);
|
OBS_GROUP_CHECKABLE, grp);
|
||||||
obs_property_set_modified_callback(p, modified_quality);
|
obs_property_set_modified_callback(p, modified_quality);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_QP_I, TRANSLATE(ST_RATECONTROL_QP_I),
|
auto p =
|
||||||
0, 51, 1);
|
obs_properties_add_int_slider(grp, ST_RATECONTROL_QP_I, D_TRANSLATE(ST_RATECONTROL_QP_I), 0, 51, 1);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_QP_I)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_QP_I)));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_QP_I_INITIAL,
|
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_QP_I_INITIAL,
|
||||||
TRANSLATE(ST_RATECONTROL_QP_I_INITIAL), -1, 51, 1);
|
D_TRANSLATE(ST_RATECONTROL_QP_I_INITIAL), -1, 51, 1);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_QP_I_INITIAL)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_QP_I_INITIAL)));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_QP_P, TRANSLATE(ST_RATECONTROL_QP_P),
|
auto p =
|
||||||
0, 51, 1);
|
obs_properties_add_int_slider(grp, ST_RATECONTROL_QP_P, D_TRANSLATE(ST_RATECONTROL_QP_P), 0, 51, 1);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_QP_P)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_QP_P)));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_QP_P_INITIAL,
|
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_QP_P_INITIAL,
|
||||||
TRANSLATE(ST_RATECONTROL_QP_P_INITIAL), -1, 51, 1);
|
D_TRANSLATE(ST_RATECONTROL_QP_P_INITIAL), -1, 51, 1);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_QP_P_INITIAL)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_QP_P_INITIAL)));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_QP_B, TRANSLATE(ST_RATECONTROL_QP_B),
|
auto p =
|
||||||
0, 51, 1);
|
obs_properties_add_int_slider(grp, ST_RATECONTROL_QP_B, D_TRANSLATE(ST_RATECONTROL_QP_B), 0, 51, 1);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_QP_B)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_QP_B)));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_QP_B_INITIAL,
|
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_QP_B_INITIAL,
|
||||||
TRANSLATE(ST_RATECONTROL_QP_B_INITIAL), -1, 51, 1);
|
D_TRANSLATE(ST_RATECONTROL_QP_B_INITIAL), -1, 51, 1);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_QP_B_INITIAL)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_QP_B_INITIAL)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
obs_properties_t* grp = props;
|
obs_properties_t* grp = props;
|
||||||
if (!obsffmpeg::are_property_groups_broken()) {
|
if (!util::are_property_groups_broken()) {
|
||||||
grp = obs_properties_create();
|
grp = obs_properties_create();
|
||||||
obs_properties_add_group(props, ST_AQ, TRANSLATE(ST_AQ), OBS_GROUP_NORMAL, grp);
|
obs_properties_add_group(props, ST_AQ, D_TRANSLATE(ST_AQ), OBS_GROUP_NORMAL, grp);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_AQ_SPATIAL, TRANSLATE(ST_AQ_SPATIAL));
|
auto p = util::obs_properties_add_tristate(grp, ST_AQ_SPATIAL, D_TRANSLATE(ST_AQ_SPATIAL));
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_AQ_SPATIAL)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_AQ_SPATIAL)));
|
||||||
obs_property_set_modified_callback(p, modified_aq);
|
obs_property_set_modified_callback(p, modified_aq);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto p =
|
auto p = obs_properties_add_int_slider(grp, ST_AQ_STRENGTH, D_TRANSLATE(ST_AQ_STRENGTH), 1, 15, 1);
|
||||||
obs_properties_add_int_slider(grp, ST_AQ_STRENGTH, TRANSLATE(ST_AQ_STRENGTH), 1, 15, 1);
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_AQ_STRENGTH)));
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_AQ_STRENGTH)));
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_AQ_TEMPORAL, TRANSLATE(ST_AQ_TEMPORAL));
|
auto p = util::obs_properties_add_tristate(grp, ST_AQ_TEMPORAL, D_TRANSLATE(ST_AQ_TEMPORAL));
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_AQ_TEMPORAL)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_AQ_TEMPORAL)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
obs_properties_t* grp = props;
|
obs_properties_t* grp = props;
|
||||||
if (!obsffmpeg::are_property_groups_broken()) {
|
if (!util::are_property_groups_broken()) {
|
||||||
grp = obs_properties_create();
|
grp = obs_properties_create();
|
||||||
obs_properties_add_group(props, ST_OTHER, TRANSLATE(ST_OTHER), OBS_GROUP_NORMAL, grp);
|
obs_properties_add_group(props, ST_OTHER, D_TRANSLATE(ST_OTHER), OBS_GROUP_NORMAL, grp);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto p =
|
auto p = obs_properties_add_int_slider(grp, ST_OTHER_BFRAMES, D_TRANSLATE(ST_OTHER_BFRAMES), 0, 4, 1);
|
||||||
obs_properties_add_int_slider(grp, ST_OTHER_BFRAMES, TRANSLATE(ST_OTHER_BFRAMES), 0, 4, 1);
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_OTHER_BFRAMES)));
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_OTHER_BFRAMES)));
|
|
||||||
obs_property_int_set_suffix(p, " frames");
|
obs_property_int_set_suffix(p, " frames");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_list(grp, ST_OTHER_BFRAME_REFERENCEMODE,
|
auto p =
|
||||||
TRANSLATE(ST_OTHER_BFRAME_REFERENCEMODE), OBS_COMBO_TYPE_LIST,
|
obs_properties_add_list(grp, ST_OTHER_BFRAME_REFERENCEMODE, D_TRANSLATE(ST_OTHER_BFRAME_REFERENCEMODE),
|
||||||
OBS_COMBO_FORMAT_INT);
|
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_OTHER_BFRAME_REFERENCEMODE)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_OTHER_BFRAME_REFERENCEMODE)));
|
||||||
for (auto kv : b_ref_modes) {
|
for (auto kv : b_ref_modes) {
|
||||||
obs_property_list_add_int(p, TRANSLATE(kv.second.c_str()),
|
obs_property_list_add_int(p, D_TRANSLATE(kv.second.c_str()), static_cast<int64_t>(kv.first));
|
||||||
static_cast<int64_t>(kv.first));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_OTHER_ZEROLATENCY,
|
auto p = util::obs_properties_add_tristate(grp, ST_OTHER_ZEROLATENCY, D_TRANSLATE(ST_OTHER_ZEROLATENCY));
|
||||||
TRANSLATE(ST_OTHER_ZEROLATENCY));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_OTHER_ZEROLATENCY)));
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_OTHER_ZEROLATENCY)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_OTHER_WEIGHTED_PREDICTION,
|
auto p = util::obs_properties_add_tristate(grp, ST_OTHER_WEIGHTED_PREDICTION,
|
||||||
TRANSLATE(ST_OTHER_WEIGHTED_PREDICTION));
|
D_TRANSLATE(ST_OTHER_WEIGHTED_PREDICTION));
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_OTHER_WEIGHTED_PREDICTION)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_OTHER_WEIGHTED_PREDICTION)));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_OTHER_NONREFERENCE_PFRAMES,
|
auto p = util::obs_properties_add_tristate(grp, ST_OTHER_NONREFERENCE_PFRAMES,
|
||||||
TRANSLATE(ST_OTHER_NONREFERENCE_PFRAMES));
|
D_TRANSLATE(ST_OTHER_NONREFERENCE_PFRAMES));
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(ST_OTHER_NONREFERENCE_PFRAMES)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_OTHER_NONREFERENCE_PFRAMES)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::nvenc::get_runtime_properties(obs_properties_t* props, const AVCodec*, AVCodecContext*)
|
void nvenc::get_runtime_properties(obs_properties_t* props, const AVCodec*, AVCodecContext*)
|
||||||
{
|
{
|
||||||
obs_property_set_enabled(obs_properties_get(props, ST_PRESET), false);
|
obs_property_set_enabled(obs_properties_get(props, ST_PRESET), false);
|
||||||
obs_property_set_enabled(obs_properties_get(props, ST_RATECONTROL), false);
|
obs_property_set_enabled(obs_properties_get(props, ST_RATECONTROL), false);
|
||||||
|
@ -532,7 +525,7 @@ void obsffmpeg::nvenc::get_runtime_properties(obs_properties_t* props, const AVC
|
||||||
obs_property_set_enabled(obs_properties_get(props, ST_OTHER_NONREFERENCE_PFRAMES), false);
|
obs_property_set_enabled(obs_properties_get(props, ST_OTHER_NONREFERENCE_PFRAMES), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context)
|
void nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
preset c_preset = static_cast<preset>(obs_data_get_int(settings, ST_PRESET));
|
preset c_preset = static_cast<preset>(obs_data_get_int(settings, ST_PRESET));
|
||||||
|
@ -552,8 +545,8 @@ void obsffmpeg::nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCode
|
||||||
bool have_qp_init = false;
|
bool have_qp_init = false;
|
||||||
|
|
||||||
ratecontrolmode rc = static_cast<ratecontrolmode>(obs_data_get_int(settings, ST_RATECONTROL_MODE));
|
ratecontrolmode rc = static_cast<ratecontrolmode>(obs_data_get_int(settings, ST_RATECONTROL_MODE));
|
||||||
auto rcopt = nvenc::ratecontrolmode_to_opt.find(rc);
|
auto rcopt = ratecontrolmode_to_opt.find(rc);
|
||||||
if (rcopt != nvenc::ratecontrolmode_to_opt.end()) {
|
if (rcopt != ratecontrolmode_to_opt.end()) {
|
||||||
av_opt_set(context->priv_data, "rc", rcopt->second.c_str(), 0);
|
av_opt_set(context->priv_data, "rc", rcopt->second.c_str(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,6 +555,7 @@ void obsffmpeg::nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCode
|
||||||
case ratecontrolmode::CQP:
|
case ratecontrolmode::CQP:
|
||||||
have_qp = true;
|
have_qp = true;
|
||||||
break;
|
break;
|
||||||
|
case ratecontrolmode::INVALID:
|
||||||
case ratecontrolmode::CBR:
|
case ratecontrolmode::CBR:
|
||||||
case ratecontrolmode::CBR_HQ:
|
case ratecontrolmode::CBR_HQ:
|
||||||
case ratecontrolmode::CBR_LD_HQ:
|
case ratecontrolmode::CBR_LD_HQ:
|
||||||
|
@ -586,38 +580,33 @@ void obsffmpeg::nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCode
|
||||||
av_opt_set_int(context->priv_data, "rc-lookahead", la, 0);
|
av_opt_set_int(context->priv_data, "rc-lookahead", la, 0);
|
||||||
if (la > 0) {
|
if (la > 0) {
|
||||||
int64_t adapt_i = obs_data_get_int(settings, ST_RATECONTROL_ADAPTIVEI);
|
int64_t adapt_i = obs_data_get_int(settings, ST_RATECONTROL_ADAPTIVEI);
|
||||||
if (!is_tristate_default(adapt_i)) {
|
if (!util::is_tristate_default(adapt_i)) {
|
||||||
av_opt_set_int(context->priv_data, "no-scenecut", adapt_i, AV_OPT_SEARCH_CHILDREN);
|
av_opt_set_int(context->priv_data, "no-scenecut", adapt_i, AV_OPT_SEARCH_CHILDREN);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(codec->name, "h264_nvenc")) {
|
if (strcmp(codec->name, "h264_nvenc")) {
|
||||||
int64_t adapt_b = obs_data_get_int(settings, ST_RATECONTROL_ADAPTIVEB);
|
int64_t adapt_b = obs_data_get_int(settings, ST_RATECONTROL_ADAPTIVEB);
|
||||||
if (!is_tristate_default(adapt_b)) {
|
if (!util::is_tristate_default(adapt_b)) {
|
||||||
av_opt_set_int(context->priv_data, "b_adapt", adapt_b, AV_OPT_SEARCH_CHILDREN);
|
av_opt_set_int(context->priv_data, "b_adapt", adapt_b, AV_OPT_SEARCH_CHILDREN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (have_bitrate) {
|
if (have_bitrate) {
|
||||||
context->bit_rate =
|
context->bit_rate = static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_BITRATE_TARGET) * 1000);
|
||||||
static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_BITRATE_TARGET) * 1000);
|
|
||||||
// Support for Replay Buffer
|
// Support for Replay Buffer
|
||||||
obs_data_set_int(settings, "bitrate",
|
obs_data_set_int(settings, "bitrate", obs_data_get_int(settings, ST_RATECONTROL_BITRATE_TARGET));
|
||||||
obs_data_get_int(settings, ST_RATECONTROL_BITRATE_TARGET));
|
|
||||||
}
|
}
|
||||||
if (have_bitrate_max)
|
if (have_bitrate_max)
|
||||||
context->rc_max_rate =
|
context->rc_max_rate = static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_BITRATE_MAXIMUM) * 1000);
|
||||||
static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_BITRATE_MAXIMUM) * 1000);
|
|
||||||
if (have_bitrate || have_bitrate_max)
|
if (have_bitrate || have_bitrate_max)
|
||||||
context->rc_buffer_size =
|
context->rc_buffer_size = static_cast<int>(obs_data_get_int(settings, S_RATECONTROL_BUFFERSIZE) * 1000);
|
||||||
static_cast<int>(obs_data_get_int(settings, S_RATECONTROL_BUFFERSIZE) * 1000);
|
|
||||||
|
|
||||||
if (have_quality && obs_data_get_bool(settings, ST_RATECONTROL_QUALITY)) {
|
if (have_quality && obs_data_get_bool(settings, ST_RATECONTROL_QUALITY)) {
|
||||||
int qmin = static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_QUALITY_MINIMUM));
|
int qmin = static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_QUALITY_MINIMUM));
|
||||||
context->qmin = qmin;
|
context->qmin = qmin;
|
||||||
if (qmin >= 0) {
|
if (qmin >= 0) {
|
||||||
context->qmax =
|
context->qmax = static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_QUALITY_MAXIMUM));
|
||||||
static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_QUALITY_MAXIMUM));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,19 +619,16 @@ void obsffmpeg::nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCode
|
||||||
|
|
||||||
if (have_qp) {
|
if (have_qp) {
|
||||||
av_opt_set_int(context->priv_data, "init_qpI",
|
av_opt_set_int(context->priv_data, "init_qpI",
|
||||||
static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_QP_I)), 0);
|
static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_QP_I)), 0);
|
||||||
av_opt_set_int(context->priv_data, "init_qpP",
|
av_opt_set_int(context->priv_data, "init_qpP",
|
||||||
static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_QP_P)), 0);
|
static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_QP_P)), 0);
|
||||||
av_opt_set_int(context->priv_data, "init_qpB",
|
av_opt_set_int(context->priv_data, "init_qpB",
|
||||||
static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_QP_B)), 0);
|
static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_QP_B)), 0);
|
||||||
}
|
}
|
||||||
if (have_qp_init) {
|
if (have_qp_init) {
|
||||||
av_opt_set_int(context->priv_data, "init_qpI",
|
av_opt_set_int(context->priv_data, "init_qpI", obs_data_get_int(settings, ST_RATECONTROL_QP_I_INITIAL), 0);
|
||||||
obs_data_get_int(settings, ST_RATECONTROL_QP_I_INITIAL), 0);
|
av_opt_set_int(context->priv_data, "init_qpP", obs_data_get_int(settings, ST_RATECONTROL_QP_P_INITIAL), 0);
|
||||||
av_opt_set_int(context->priv_data, "init_qpP",
|
av_opt_set_int(context->priv_data, "init_qpB", obs_data_get_int(settings, ST_RATECONTROL_QP_B_INITIAL), 0);
|
||||||
obs_data_get_int(settings, ST_RATECONTROL_QP_P_INITIAL), 0);
|
|
||||||
av_opt_set_int(context->priv_data, "init_qpB",
|
|
||||||
obs_data_get_int(settings, ST_RATECONTROL_QP_B_INITIAL), 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -651,19 +637,19 @@ void obsffmpeg::nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCode
|
||||||
int64_t taq = obs_data_get_int(settings, ST_AQ_TEMPORAL);
|
int64_t taq = obs_data_get_int(settings, ST_AQ_TEMPORAL);
|
||||||
|
|
||||||
if (strcmp(codec->name, "h264_nvenc") == 0) {
|
if (strcmp(codec->name, "h264_nvenc") == 0) {
|
||||||
if (!is_tristate_default(saq))
|
if (!util::is_tristate_default(saq))
|
||||||
av_opt_set_int(context->priv_data, "spatial-aq", saq, 0);
|
av_opt_set_int(context->priv_data, "spatial-aq", saq, 0);
|
||||||
if (!is_tristate_default(taq))
|
if (!util::is_tristate_default(taq))
|
||||||
av_opt_set_int(context->priv_data, "temporal-aq", taq, 0);
|
av_opt_set_int(context->priv_data, "temporal-aq", taq, 0);
|
||||||
} else {
|
} else {
|
||||||
if (!is_tristate_default(saq))
|
if (!util::is_tristate_default(saq))
|
||||||
av_opt_set_int(context->priv_data, "spatial_aq", saq, 0);
|
av_opt_set_int(context->priv_data, "spatial_aq", saq, 0);
|
||||||
if (!is_tristate_default(taq))
|
if (!util::is_tristate_default(taq))
|
||||||
av_opt_set_int(context->priv_data, "temporal_aq", taq, 0);
|
av_opt_set_int(context->priv_data, "temporal_aq", taq, 0);
|
||||||
}
|
}
|
||||||
if (is_tristate_enabled(saq))
|
if (util::is_tristate_enabled(saq))
|
||||||
av_opt_set_int(context->priv_data, "aq-strength",
|
av_opt_set_int(context->priv_data, "aq-strength",
|
||||||
static_cast<int>(obs_data_get_int(settings, ST_AQ_STRENGTH)), 0);
|
static_cast<int>(obs_data_get_int(settings, ST_AQ_STRENGTH)), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // Other
|
{ // Other
|
||||||
|
@ -673,21 +659,21 @@ void obsffmpeg::nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCode
|
||||||
|
|
||||||
context->max_b_frames = static_cast<int>(obs_data_get_int(settings, ST_OTHER_BFRAMES));
|
context->max_b_frames = static_cast<int>(obs_data_get_int(settings, ST_OTHER_BFRAMES));
|
||||||
|
|
||||||
if (!is_tristate_default(zl))
|
if (!util::is_tristate_default(zl))
|
||||||
av_opt_set_int(context->priv_data, "zerolatency", zl, 0);
|
av_opt_set_int(context->priv_data, "zerolatency", zl, 0);
|
||||||
if (!is_tristate_default(nrp))
|
if (!util::is_tristate_default(nrp))
|
||||||
av_opt_set_int(context->priv_data, "nonref_p", nrp, 0);
|
av_opt_set_int(context->priv_data, "nonref_p", nrp, 0);
|
||||||
|
|
||||||
if ((context->max_b_frames != 0) && is_tristate_enabled(wp)) {
|
if ((context->max_b_frames != 0) && util::is_tristate_enabled(wp)) {
|
||||||
PLOG_WARNING("[%s] Weighted Prediction disabled because of B-Frames being used.", codec->name);
|
LOG_WARNING("[%s] Weighted Prediction disabled because of B-Frames being used.", codec->name);
|
||||||
av_opt_set_int(context->priv_data, "weighted_pred", 0, 0);
|
av_opt_set_int(context->priv_data, "weighted_pred", 0, 0);
|
||||||
} else if (!is_tristate_default(wp)) {
|
} else if (!util::is_tristate_default(wp)) {
|
||||||
av_opt_set_int(context->priv_data, "weighted_pred", wp, 0);
|
av_opt_set_int(context->priv_data, "weighted_pred", wp, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto found = b_ref_mode_to_opt.find(
|
auto found = b_ref_mode_to_opt.find(
|
||||||
static_cast<b_ref_mode>(obs_data_get_int(settings, ST_OTHER_BFRAME_REFERENCEMODE)));
|
static_cast<b_ref_mode>(obs_data_get_int(settings, ST_OTHER_BFRAME_REFERENCEMODE)));
|
||||||
if (found != b_ref_mode_to_opt.end()) {
|
if (found != b_ref_mode_to_opt.end()) {
|
||||||
av_opt_set(context->priv_data, "b_ref_mode", found->second.c_str(), 0);
|
av_opt_set(context->priv_data, "b_ref_mode", found->second.c_str(), 0);
|
||||||
}
|
}
|
||||||
|
@ -695,10 +681,10 @@ void obsffmpeg::nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::nvenc::log_options(obs_data_t*, const AVCodec* codec, AVCodecContext* context)
|
void nvenc::log_options(obs_data_t*, const AVCodec* codec, AVCodecContext* context)
|
||||||
{
|
{
|
||||||
PLOG_INFO("[%s] Nvidia NVENC:", codec->name);
|
LOG_INFO("[%s] Nvidia NVENC:", codec->name);
|
||||||
ffmpeg::tools::print_av_option_string(context, "preset", " Preset", [](int64_t v) {
|
tools::print_av_option_string(context, "preset", " Preset", [](int64_t v) {
|
||||||
preset val = static_cast<preset>(v);
|
preset val = static_cast<preset>(v);
|
||||||
std::string name = "<Unknown>";
|
std::string name = "<Unknown>";
|
||||||
auto index = preset_to_opt.find(val);
|
auto index = preset_to_opt.find(val);
|
||||||
|
@ -706,7 +692,7 @@ void obsffmpeg::nvenc::log_options(obs_data_t*, const AVCodec* codec, AVCodecCon
|
||||||
name = index->second;
|
name = index->second;
|
||||||
return name;
|
return name;
|
||||||
});
|
});
|
||||||
ffmpeg::tools::print_av_option_string(context, "rc", " Rate Control", [](int64_t v) {
|
tools::print_av_option_string(context, "rc", " Rate Control", [](int64_t v) {
|
||||||
ratecontrolmode val = static_cast<ratecontrolmode>(v);
|
ratecontrolmode val = static_cast<ratecontrolmode>(v);
|
||||||
std::string name = "<Unknown>";
|
std::string name = "<Unknown>";
|
||||||
auto index = ratecontrolmode_to_opt.find(val);
|
auto index = ratecontrolmode_to_opt.find(val);
|
||||||
|
@ -714,27 +700,27 @@ void obsffmpeg::nvenc::log_options(obs_data_t*, const AVCodec* codec, AVCodecCon
|
||||||
name = index->second;
|
name = index->second;
|
||||||
return name;
|
return name;
|
||||||
});
|
});
|
||||||
ffmpeg::tools::print_av_option_bool(context, "2pass", " Two Pass");
|
tools::print_av_option_bool(context, "2pass", " Two Pass");
|
||||||
ffmpeg::tools::print_av_option_int(context, "rc-lookahead", " Look-Ahead", "Frames");
|
tools::print_av_option_int(context, "rc-lookahead", " Look-Ahead", "Frames");
|
||||||
ffmpeg::tools::print_av_option_bool(context, "no-scenecut", " Adaptive I-Frames");
|
tools::print_av_option_bool(context, "no-scenecut", " Adaptive I-Frames");
|
||||||
if (strcmp(codec->name, "h264_nvenc") == 0)
|
if (strcmp(codec->name, "h264_nvenc") == 0)
|
||||||
ffmpeg::tools::print_av_option_bool(context, "b_adapt", " Adaptive B-Frames");
|
tools::print_av_option_bool(context, "b_adapt", " Adaptive B-Frames");
|
||||||
|
|
||||||
PLOG_INFO("[%s] Bitrate:", codec->name);
|
LOG_INFO("[%s] Bitrate:", codec->name);
|
||||||
ffmpeg::tools::print_av_option_int(context, "bitrate", " Target", "bits/sec");
|
tools::print_av_option_int(context, "bitrate", " Target", "bits/sec");
|
||||||
ffmpeg::tools::print_av_option_int(context, "rc_max_rate", " Maximum", "bits/sec");
|
tools::print_av_option_int(context, "rc_max_rate", " Maximum", "bits/sec");
|
||||||
ffmpeg::tools::print_av_option_int(context, "rc_buffer_size", " Buffer", "bits");
|
tools::print_av_option_int(context, "rc_buffer_size", " Buffer", "bits");
|
||||||
PLOG_INFO("[%s] Quality:", codec->name);
|
LOG_INFO("[%s] Quality:", codec->name);
|
||||||
ffmpeg::tools::print_av_option_int(context, "qmin", " Minimum", "");
|
tools::print_av_option_int(context, "qmin", " Minimum", "");
|
||||||
ffmpeg::tools::print_av_option_int(context, "cq", " Target", "");
|
tools::print_av_option_int(context, "cq", " Target", "");
|
||||||
ffmpeg::tools::print_av_option_int(context, "qmax", " Maximum", "");
|
tools::print_av_option_int(context, "qmax", " Maximum", "");
|
||||||
PLOG_INFO("[%s] Quantization Parameters:", codec->name);
|
LOG_INFO("[%s] Quantization Parameters:", codec->name);
|
||||||
ffmpeg::tools::print_av_option_int(context, "init_qpI", " I-Frame", "");
|
tools::print_av_option_int(context, "init_qpI", " I-Frame", "");
|
||||||
ffmpeg::tools::print_av_option_int(context, "init_qpP", " P-Frame", "");
|
tools::print_av_option_int(context, "init_qpP", " P-Frame", "");
|
||||||
ffmpeg::tools::print_av_option_int(context, "init_qpB", " B-Frame", "");
|
tools::print_av_option_int(context, "init_qpB", " B-Frame", "");
|
||||||
|
|
||||||
ffmpeg::tools::print_av_option_int(context, "max_b_frames", " B-Frames", "Frames");
|
tools::print_av_option_int(context, "max_b_frames", " B-Frames", "Frames");
|
||||||
ffmpeg::tools::print_av_option_string(context, "b_ref_mode", " Reference Mode", [](int64_t v) {
|
tools::print_av_option_string(context, "b_ref_mode", " Reference Mode", [](int64_t v) {
|
||||||
b_ref_mode val = static_cast<b_ref_mode>(v);
|
b_ref_mode val = static_cast<b_ref_mode>(v);
|
||||||
std::string name = "<Unknown>";
|
std::string name = "<Unknown>";
|
||||||
auto index = b_ref_mode_to_opt.find(val);
|
auto index = b_ref_mode_to_opt.find(val);
|
||||||
|
@ -743,25 +729,25 @@ void obsffmpeg::nvenc::log_options(obs_data_t*, const AVCodec* codec, AVCodecCon
|
||||||
return name;
|
return name;
|
||||||
});
|
});
|
||||||
|
|
||||||
PLOG_INFO("[%s] Adaptive Quantization:", codec->name);
|
LOG_INFO("[%s] Adaptive Quantization:", codec->name);
|
||||||
if (strcmp(codec->name, "h264_nvenc") == 0) {
|
if (strcmp(codec->name, "h264_nvenc") == 0) {
|
||||||
ffmpeg::tools::print_av_option_bool(context, "spatial-aq", " Spatial AQ");
|
tools::print_av_option_bool(context, "spatial-aq", " Spatial AQ");
|
||||||
ffmpeg::tools::print_av_option_int(context, "aq-strength", " Strength", "");
|
tools::print_av_option_int(context, "aq-strength", " Strength", "");
|
||||||
ffmpeg::tools::print_av_option_bool(context, "temporal-aq", " Temporal AQ");
|
tools::print_av_option_bool(context, "temporal-aq", " Temporal AQ");
|
||||||
} else {
|
} else {
|
||||||
ffmpeg::tools::print_av_option_bool(context, "spatial_aq", " Spatial AQ");
|
tools::print_av_option_bool(context, "spatial_aq", " Spatial AQ");
|
||||||
ffmpeg::tools::print_av_option_int(context, "aq-strength", " Strength", "");
|
tools::print_av_option_int(context, "aq-strength", " Strength", "");
|
||||||
ffmpeg::tools::print_av_option_bool(context, "temporal_aq", " Temporal AQ");
|
tools::print_av_option_bool(context, "temporal_aq", " Temporal AQ");
|
||||||
}
|
}
|
||||||
|
|
||||||
PLOG_INFO("[%s] Other:", codec->name);
|
LOG_INFO("[%s] Other:", codec->name);
|
||||||
ffmpeg::tools::print_av_option_bool(context, "zerolatency", " Zero Latency");
|
tools::print_av_option_bool(context, "zerolatency", " Zero Latency");
|
||||||
ffmpeg::tools::print_av_option_bool(context, "weighted_pred", " Weighted Prediction");
|
tools::print_av_option_bool(context, "weighted_pred", " Weighted Prediction");
|
||||||
ffmpeg::tools::print_av_option_bool(context, "nonref_p", " Non-reference P-Frames");
|
tools::print_av_option_bool(context, "nonref_p", " Non-reference P-Frames");
|
||||||
ffmpeg::tools::print_av_option_bool(context, "strict_gop", " Strict GOP");
|
tools::print_av_option_bool(context, "strict_gop", " Strict GOP");
|
||||||
ffmpeg::tools::print_av_option_bool(context, "aud", " Access Unit Delimiters");
|
tools::print_av_option_bool(context, "aud", " Access Unit Delimiters");
|
||||||
ffmpeg::tools::print_av_option_bool(context, "bluray-compat", " Bluray Compatibility");
|
tools::print_av_option_bool(context, "bluray-compat", " Bluray Compatibility");
|
||||||
if (strcmp(codec->name, "h264_nvenc") == 0)
|
if (strcmp(codec->name, "h264_nvenc") == 0)
|
||||||
ffmpeg::tools::print_av_option_bool(context, "a53cc", " A53 Closed Captions");
|
tools::print_av_option_bool(context, "a53cc", " A53 Closed Captions");
|
||||||
ffmpeg::tools::print_av_option_int(context, "dpb_size", " DPB Size", "");
|
tools::print_av_option_int(context, "dpb_size", " DPB Size", "");
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include "handler.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -31,70 +33,68 @@ extern "C" {
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace obsffmpeg {
|
using namespace encoder::ffmpeg;
|
||||||
class encoder;
|
|
||||||
|
|
||||||
namespace nvenc {
|
namespace encoder::ffmpeg::handler::nvenc {
|
||||||
enum class preset : int64_t {
|
enum class preset : int64_t {
|
||||||
DEFAULT,
|
DEFAULT,
|
||||||
SLOW,
|
SLOW,
|
||||||
MEDIUM,
|
MEDIUM,
|
||||||
FAST,
|
FAST,
|
||||||
HIGH_PERFORMANCE,
|
HIGH_PERFORMANCE,
|
||||||
HIGH_QUALITY,
|
HIGH_QUALITY,
|
||||||
BLURAYDISC,
|
BLURAYDISC,
|
||||||
LOW_LATENCY,
|
LOW_LATENCY,
|
||||||
LOW_LATENCY_HIGH_PERFORMANCE,
|
LOW_LATENCY_HIGH_PERFORMANCE,
|
||||||
LOW_LATENCY_HIGH_QUALITY,
|
LOW_LATENCY_HIGH_QUALITY,
|
||||||
LOSSLESS,
|
LOSSLESS,
|
||||||
LOSSLESS_HIGH_PERFORMANCE,
|
LOSSLESS_HIGH_PERFORMANCE,
|
||||||
// Append things before this.
|
// Append things before this.
|
||||||
INVALID = -1,
|
INVALID = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ratecontrolmode : int64_t {
|
enum class ratecontrolmode : int64_t {
|
||||||
CQP,
|
CQP,
|
||||||
VBR,
|
VBR,
|
||||||
VBR_HQ,
|
VBR_HQ,
|
||||||
CBR,
|
CBR,
|
||||||
CBR_HQ,
|
CBR_HQ,
|
||||||
CBR_LD_HQ,
|
CBR_LD_HQ,
|
||||||
// Append things before this.
|
// Append things before this.
|
||||||
INVALID = -1,
|
INVALID = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class b_ref_mode : int64_t {
|
enum class b_ref_mode : int64_t {
|
||||||
DISABLED,
|
DISABLED,
|
||||||
EACH,
|
EACH,
|
||||||
MIDDLE,
|
MIDDLE,
|
||||||
// Append things before this.
|
// Append things before this.
|
||||||
INVALID = -1,
|
INVALID = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::map<preset, std::string> presets;
|
extern std::map<preset, std::string> presets;
|
||||||
|
|
||||||
extern std::map<preset, std::string> preset_to_opt;
|
extern std::map<preset, std::string> preset_to_opt;
|
||||||
|
|
||||||
extern std::map<ratecontrolmode, std::string> ratecontrolmodes;
|
extern std::map<ratecontrolmode, std::string> ratecontrolmodes;
|
||||||
|
|
||||||
extern std::map<ratecontrolmode, std::string> ratecontrolmode_to_opt;
|
extern std::map<ratecontrolmode, std::string> ratecontrolmode_to_opt;
|
||||||
|
|
||||||
extern std::map<b_ref_mode, std::string> b_ref_modes;
|
extern std::map<b_ref_mode, std::string> b_ref_modes;
|
||||||
|
|
||||||
extern std::map<b_ref_mode, std::string> b_ref_mode_to_opt;
|
extern std::map<b_ref_mode, std::string> b_ref_mode_to_opt;
|
||||||
|
|
||||||
void override_update(obsffmpeg::encoder* instance, obs_data_t* settings);
|
void override_update(ffmpeg_instance* instance, obs_data_t* settings);
|
||||||
|
|
||||||
void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
||||||
|
|
||||||
void get_properties_pre(obs_properties_t* props, const AVCodec* codec);
|
void get_properties_pre(obs_properties_t* props, const AVCodec* codec);
|
||||||
|
|
||||||
void get_properties_post(obs_properties_t* props, const AVCodec* codec);
|
void get_properties_post(obs_properties_t* props, const AVCodec* codec);
|
||||||
|
|
||||||
void get_runtime_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context);
|
void get_runtime_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context);
|
||||||
|
|
||||||
void update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
void update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
||||||
|
|
||||||
void log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
void log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
|
||||||
} // namespace nvenc
|
} // namespace encoder::ffmpeg::handler::nvenc
|
||||||
} // namespace obsffmpeg
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
|
|
||||||
#include "prores_aw_handler.hpp"
|
#include "prores_aw_handler.hpp"
|
||||||
#include "codecs/prores.hpp"
|
#include "../codecs/prores.hpp"
|
||||||
#include "ffmpeg/tools.hpp"
|
#include "ffmpeg/tools.hpp"
|
||||||
#include "plugin.hpp"
|
#include "plugin.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
@ -29,15 +29,10 @@ extern "C" {
|
||||||
#include <obs-module.h>
|
#include <obs-module.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
INITIALIZER(prores_aw_handler_init)
|
using namespace encoder::ffmpeg::handler;
|
||||||
{
|
|
||||||
obsffmpeg::initializers.push_back([]() {
|
|
||||||
obsffmpeg::register_codec_handler("prores_aw", std::make_shared<obsffmpeg::ui::prores_aw_handler>());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
void obsffmpeg::ui::prores_aw_handler::override_colorformat(AVPixelFormat& target_format, obs_data_t* settings,
|
void prores_aw_handler::override_colorformat(AVPixelFormat& target_format, obs_data_t* settings, const AVCodec* codec,
|
||||||
const AVCodec* codec, AVCodecContext*)
|
AVCodecContext*)
|
||||||
{
|
{
|
||||||
std::string profile = "";
|
std::string profile = "";
|
||||||
|
|
||||||
|
@ -50,7 +45,7 @@ void obsffmpeg::ui::prores_aw_handler::override_colorformat(AVPixelFormat& targe
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<AVPixelFormat, std::list<std::string>> valid_formats = {
|
std::unordered_map<AVPixelFormat, std::list<std::string>> valid_formats = {
|
||||||
{AV_PIX_FMT_YUV422P10, {"apco", "apcs", "apcn", "apch"}}, {AV_PIX_FMT_YUV444P10, {"ap4h", "ap4x"}}};
|
{AV_PIX_FMT_YUV422P10, {"apco", "apcs", "apcn", "apch"}}, {AV_PIX_FMT_YUV444P10, {"ap4h", "ap4x"}}};
|
||||||
|
|
||||||
for (auto kv : valid_formats) {
|
for (auto kv : valid_formats) {
|
||||||
for (auto name : kv.second) {
|
for (auto name : kv.second) {
|
||||||
|
@ -61,7 +56,7 @@ void obsffmpeg::ui::prores_aw_handler::override_colorformat(AVPixelFormat& targe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::prores_aw_handler::get_defaults(obs_data_t* settings, const AVCodec*, AVCodecContext*, bool)
|
void prores_aw_handler::get_defaults(obs_data_t* settings, const AVCodec*, AVCodecContext*, bool)
|
||||||
{
|
{
|
||||||
obs_data_set_default_int(settings, P_PRORES_PROFILE, 0);
|
obs_data_set_default_int(settings, P_PRORES_PROFILE, 0);
|
||||||
}
|
}
|
||||||
|
@ -70,29 +65,28 @@ inline const char* profile_to_name(const AVProfile* ptr)
|
||||||
{
|
{
|
||||||
switch (ptr->profile) {
|
switch (ptr->profile) {
|
||||||
case 0:
|
case 0:
|
||||||
return TRANSLATE(P_PRORES_PROFILE_APCO);
|
return D_TRANSLATE(P_PRORES_PROFILE_APCO);
|
||||||
case 1:
|
case 1:
|
||||||
return TRANSLATE(P_PRORES_PROFILE_APCS);
|
return D_TRANSLATE(P_PRORES_PROFILE_APCS);
|
||||||
case 2:
|
case 2:
|
||||||
return TRANSLATE(P_PRORES_PROFILE_APCN);
|
return D_TRANSLATE(P_PRORES_PROFILE_APCN);
|
||||||
case 3:
|
case 3:
|
||||||
return TRANSLATE(P_PRORES_PROFILE_APCH);
|
return D_TRANSLATE(P_PRORES_PROFILE_APCH);
|
||||||
case 4:
|
case 4:
|
||||||
return TRANSLATE(P_PRORES_PROFILE_AP4H);
|
return D_TRANSLATE(P_PRORES_PROFILE_AP4H);
|
||||||
case 5:
|
case 5:
|
||||||
return TRANSLATE(P_PRORES_PROFILE_AP4X);
|
return D_TRANSLATE(P_PRORES_PROFILE_AP4X);
|
||||||
default:
|
default:
|
||||||
return ptr->name;
|
return ptr->name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::prores_aw_handler::get_properties(obs_properties_t* props, const AVCodec* codec,
|
void prores_aw_handler::get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context, bool)
|
||||||
AVCodecContext* context, bool)
|
|
||||||
{
|
{
|
||||||
if (!context) {
|
if (!context) {
|
||||||
auto p = obs_properties_add_list(props, P_PRORES_PROFILE, TRANSLATE(P_PRORES_PROFILE),
|
auto p = obs_properties_add_list(props, P_PRORES_PROFILE, D_TRANSLATE(P_PRORES_PROFILE), OBS_COMBO_TYPE_LIST,
|
||||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
OBS_COMBO_FORMAT_INT);
|
||||||
obs_property_set_long_description(p, TRANSLATE(DESC(P_PRORES_PROFILE)));
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(P_PRORES_PROFILE)));
|
||||||
for (auto ptr = codec->profiles; ptr->profile != FF_PROFILE_UNKNOWN; ptr++) {
|
for (auto ptr = codec->profiles; ptr->profile != FF_PROFILE_UNKNOWN; ptr++) {
|
||||||
obs_property_list_add_int(p, profile_to_name(ptr), static_cast<int64_t>(ptr->profile));
|
obs_property_list_add_int(p, profile_to_name(ptr), static_cast<int64_t>(ptr->profile));
|
||||||
}
|
}
|
||||||
|
@ -101,15 +95,15 @@ void obsffmpeg::ui::prores_aw_handler::get_properties(obs_properties_t* props, c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::prores_aw_handler::update(obs_data_t* settings, const AVCodec*, AVCodecContext* context)
|
void prores_aw_handler::update(obs_data_t* settings, const AVCodec*, AVCodecContext* context)
|
||||||
{
|
{
|
||||||
context->profile = static_cast<int>(obs_data_get_int(settings, P_PRORES_PROFILE));
|
context->profile = static_cast<int>(obs_data_get_int(settings, P_PRORES_PROFILE));
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::prores_aw_handler::log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context)
|
void prores_aw_handler::log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context)
|
||||||
{
|
{
|
||||||
PLOG_INFO("[%s] Apple ProRes:", codec->name);
|
LOG_INFO("[%s] Apple ProRes:", codec->name);
|
||||||
ffmpeg::tools::print_av_option_string(context, "profile", " Profile", [&codec](int64_t v) {
|
::ffmpeg::tools::print_av_option_string(context, "profile", " Profile", [&codec](int64_t v) {
|
||||||
int val = static_cast<int>(v);
|
int val = static_cast<int>(v);
|
||||||
for (auto ptr = codec->profiles; (ptr->profile != FF_PROFILE_UNKNOWN) && (ptr != nullptr); ptr++) {
|
for (auto ptr = codec->profiles; (ptr->profile != FF_PROFILE_UNKNOWN) && (ptr != nullptr); ptr++) {
|
||||||
if (ptr->profile == val) {
|
if (ptr->profile == val) {
|
||||||
|
@ -120,7 +114,7 @@ void obsffmpeg::ui::prores_aw_handler::log_options(obs_data_t* settings, const A
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::ui::prores_aw_handler::process_avpacket(AVPacket& packet, const AVCodec*, AVCodecContext*)
|
void prores_aw_handler::process_avpacket(AVPacket& packet, const AVCodec*, AVCodecContext*)
|
||||||
{
|
{
|
||||||
//FFmpeg Bug:
|
//FFmpeg Bug:
|
||||||
// When ProRes content is stored in Matroska, FFmpeg strips the size
|
// When ProRes content is stored in Matroska, FFmpeg strips the size
|
||||||
|
|
|
@ -30,27 +30,22 @@ extern "C" {
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace obsffmpeg {
|
namespace encoder::ffmpeg::handler {
|
||||||
namespace ui {
|
class prores_aw_handler : public handler {
|
||||||
class prores_aw_handler : public handler {
|
public:
|
||||||
public:
|
virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings, const AVCodec* codec,
|
||||||
virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings,
|
AVCodecContext* context) override;
|
||||||
const AVCodec* codec, AVCodecContext* context) override;
|
|
||||||
|
|
||||||
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context,
|
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context,
|
||||||
bool hw_encode) override;
|
bool hw_encode) override;
|
||||||
|
|
||||||
virtual void get_properties(obs_properties_t* props, const AVCodec* codec,
|
virtual void get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context,
|
||||||
AVCodecContext* context, bool hw_encode) override;
|
bool hw_encode) override;
|
||||||
|
|
||||||
virtual void update(obs_data_t* settings, const AVCodec* codec,
|
virtual void update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context) override;
|
||||||
AVCodecContext* context) override;
|
|
||||||
|
|
||||||
virtual void log_options(obs_data_t* settings, const AVCodec* codec,
|
virtual void log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context) override;
|
||||||
AVCodecContext* context) override;
|
|
||||||
|
|
||||||
virtual void process_avpacket(AVPacket& packet, const AVCodec* codec,
|
virtual void process_avpacket(AVPacket& packet, const AVCodec* codec, AVCodecContext* context) override;
|
||||||
AVCodecContext* context) override;
|
};
|
||||||
};
|
} // namespace encoder::ffmpeg::handler
|
||||||
} // namespace ui
|
|
||||||
} // namespace obsffmpeg
|
|
||||||
|
|
|
@ -22,98 +22,100 @@
|
||||||
#include "avframe-queue.hpp"
|
#include "avframe-queue.hpp"
|
||||||
#include "tools.hpp"
|
#include "tools.hpp"
|
||||||
|
|
||||||
std::shared_ptr<AVFrame> ffmpeg::avframe_queue::create_frame()
|
using namespace ffmpeg;
|
||||||
|
|
||||||
|
std::shared_ptr<AVFrame> avframe_queue::create_frame()
|
||||||
{
|
{
|
||||||
std::shared_ptr<AVFrame> frame = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame* frame) {
|
std::shared_ptr<AVFrame> frame = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame* frame) {
|
||||||
av_frame_unref(frame);
|
av_frame_unref(frame);
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
});
|
});
|
||||||
frame->width = this->resolution.first;
|
frame->width = this->_resolution.first;
|
||||||
frame->height = this->resolution.second;
|
frame->height = this->_resolution.second;
|
||||||
frame->format = this->format;
|
frame->format = this->_format;
|
||||||
|
|
||||||
int res = av_frame_get_buffer(frame.get(), 32);
|
int res = av_frame_get_buffer(frame.get(), 32);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
throw std::exception(ffmpeg::tools::get_error_description(res));
|
throw std::exception(tools::get_error_description(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
ffmpeg::avframe_queue::avframe_queue() {}
|
avframe_queue::avframe_queue() {}
|
||||||
|
|
||||||
ffmpeg::avframe_queue::~avframe_queue()
|
avframe_queue::~avframe_queue()
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::avframe_queue::set_resolution(uint32_t const width, uint32_t const height)
|
void avframe_queue::set_resolution(uint32_t const width, uint32_t const height)
|
||||||
{
|
{
|
||||||
this->resolution.first = width;
|
this->_resolution.first = width;
|
||||||
this->resolution.second = height;
|
this->_resolution.second = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::avframe_queue::get_resolution(uint32_t& width, uint32_t& height)
|
void avframe_queue::get_resolution(uint32_t& width, uint32_t& height)
|
||||||
{
|
{
|
||||||
width = this->resolution.first;
|
width = this->_resolution.first;
|
||||||
height = this->resolution.second;
|
height = this->_resolution.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ffmpeg::avframe_queue::get_width()
|
uint32_t avframe_queue::get_width()
|
||||||
{
|
{
|
||||||
return this->resolution.first;
|
return this->_resolution.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ffmpeg::avframe_queue::get_height()
|
uint32_t avframe_queue::get_height()
|
||||||
{
|
{
|
||||||
return this->resolution.second;
|
return this->_resolution.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::avframe_queue::set_pixel_format(AVPixelFormat const format)
|
void avframe_queue::set_pixel_format(AVPixelFormat const format)
|
||||||
{
|
{
|
||||||
this->format = format;
|
this->_format = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
AVPixelFormat ffmpeg::avframe_queue::get_pixel_format()
|
AVPixelFormat avframe_queue::get_pixel_format()
|
||||||
{
|
{
|
||||||
return this->format;
|
return this->_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::avframe_queue::precache(size_t count)
|
void avframe_queue::precache(size_t count)
|
||||||
{
|
{
|
||||||
for (size_t n = 0; n < count; n++) {
|
for (size_t n = 0; n < count; n++) {
|
||||||
push(create_frame());
|
push(create_frame());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::avframe_queue::clear()
|
void avframe_queue::clear()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> ulock(this->lock);
|
std::unique_lock<std::mutex> ulock(this->_lock);
|
||||||
frames.clear();
|
_frames.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::avframe_queue::push(std::shared_ptr<AVFrame> const frame)
|
void avframe_queue::push(std::shared_ptr<AVFrame> const frame)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> ulock(this->lock);
|
std::unique_lock<std::mutex> ulock(this->_lock);
|
||||||
frames.push_back(frame);
|
_frames.push_back(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<AVFrame> ffmpeg::avframe_queue::pop()
|
std::shared_ptr<AVFrame> avframe_queue::pop()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> ulock(this->lock);
|
std::unique_lock<std::mutex> ulock(this->_lock);
|
||||||
std::shared_ptr<AVFrame> ret;
|
std::shared_ptr<AVFrame> ret;
|
||||||
while (ret == nullptr) {
|
while (ret == nullptr) {
|
||||||
if (frames.size() == 0) {
|
if (_frames.size() == 0) {
|
||||||
ret = create_frame();
|
ret = create_frame();
|
||||||
} else {
|
} else {
|
||||||
ret = frames.front();
|
ret = _frames.front();
|
||||||
if (ret == nullptr) {
|
if (ret == nullptr) {
|
||||||
ret = create_frame();
|
ret = create_frame();
|
||||||
} else {
|
} else {
|
||||||
frames.pop_front();
|
_frames.pop_front();
|
||||||
if ((static_cast<uint32_t>(ret->width) != this->resolution.first)
|
if ((static_cast<uint32_t>(ret->width) != this->_resolution.first)
|
||||||
|| (static_cast<uint32_t>(ret->height) != this->resolution.second)
|
|| (static_cast<uint32_t>(ret->height) != this->_resolution.second)
|
||||||
|| (ret->format != this->format)) {
|
|| (ret->format != this->_format)) {
|
||||||
ret = nullptr;
|
ret = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,26 +124,26 @@ std::shared_ptr<AVFrame> ffmpeg::avframe_queue::pop()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<AVFrame> ffmpeg::avframe_queue::pop_only()
|
std::shared_ptr<AVFrame> avframe_queue::pop_only()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> ulock(this->lock);
|
std::unique_lock<std::mutex> ulock(this->_lock);
|
||||||
if (frames.size() == 0) {
|
if (_frames.size() == 0) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
std::shared_ptr<AVFrame> ret = frames.front();
|
std::shared_ptr<AVFrame> ret = _frames.front();
|
||||||
if (ret == nullptr) {
|
if (ret == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
frames.pop_front();
|
_frames.pop_front();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ffmpeg::avframe_queue::empty()
|
bool avframe_queue::empty()
|
||||||
{
|
{
|
||||||
return frames.empty();
|
return _frames.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ffmpeg::avframe_queue::size()
|
size_t avframe_queue::size()
|
||||||
{
|
{
|
||||||
return frames.size();
|
return _frames.size();
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,11 +32,11 @@ extern "C" {
|
||||||
|
|
||||||
namespace ffmpeg {
|
namespace ffmpeg {
|
||||||
class avframe_queue {
|
class avframe_queue {
|
||||||
std::deque<std::shared_ptr<AVFrame>> frames;
|
std::deque<std::shared_ptr<AVFrame>> _frames;
|
||||||
std::mutex lock;
|
std::mutex _lock;
|
||||||
|
|
||||||
std::pair<uint32_t, uint32_t> resolution;
|
std::pair<uint32_t, uint32_t> _resolution;
|
||||||
AVPixelFormat format = AV_PIX_FMT_NONE;
|
AVPixelFormat _format = AV_PIX_FMT_NONE;
|
||||||
|
|
||||||
std::shared_ptr<AVFrame> create_frame();
|
std::shared_ptr<AVFrame> create_frame();
|
||||||
|
|
||||||
|
|
|
@ -35,36 +35,31 @@ extern "C" {
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace obsffmpeg {
|
namespace ffmpeg::hwapi {
|
||||||
namespace hwapi {
|
struct device {
|
||||||
struct device {
|
std::pair<int64_t, int64_t> id;
|
||||||
std::pair<int64_t, int64_t> id;
|
std::string name;
|
||||||
std::string name;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
class instance;
|
class instance {
|
||||||
|
public:
|
||||||
|
virtual AVBufferRef* create_device_context() = 0;
|
||||||
|
|
||||||
class base {
|
virtual std::shared_ptr<AVFrame> allocate_frame(AVBufferRef* frames) = 0;
|
||||||
public:
|
|
||||||
virtual std::list<obsffmpeg::hwapi::device> enumerate_adapters() = 0;
|
|
||||||
|
|
||||||
virtual std::shared_ptr<obsffmpeg::hwapi::instance> create(obsffmpeg::hwapi::device target) = 0;
|
virtual void copy_from_obs(AVBufferRef* frames, uint32_t handle, uint64_t lock_key, uint64_t* next_lock_key,
|
||||||
|
std::shared_ptr<AVFrame> frame) = 0;
|
||||||
|
|
||||||
virtual std::shared_ptr<obsffmpeg::hwapi::instance> create_from_obs() = 0;
|
virtual std::shared_ptr<AVFrame> avframe_from_obs(AVBufferRef* frames, uint32_t handle, uint64_t lock_key,
|
||||||
};
|
uint64_t* next_lock_key) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class instance {
|
class base {
|
||||||
public:
|
public:
|
||||||
virtual AVBufferRef* create_device_context() = 0;
|
virtual std::list<hwapi::device> enumerate_adapters() = 0;
|
||||||
|
|
||||||
virtual std::shared_ptr<AVFrame> allocate_frame(AVBufferRef* frames) = 0;
|
virtual std::shared_ptr<hwapi::instance> create(hwapi::device target) = 0;
|
||||||
|
|
||||||
virtual void copy_from_obs(AVBufferRef* frames, uint32_t handle, uint64_t lock_key,
|
virtual std::shared_ptr<hwapi::instance> create_from_obs() = 0;
|
||||||
uint64_t* next_lock_key, std::shared_ptr<AVFrame> frame) = 0;
|
};
|
||||||
|
} // namespace ffmpeg::hwapi
|
||||||
virtual std::shared_ptr<AVFrame> avframe_from_obs(AVBufferRef* frames, uint32_t handle,
|
|
||||||
uint64_t lock_key,
|
|
||||||
uint64_t* next_lock_key) = 0;
|
|
||||||
};
|
|
||||||
} // namespace hwapi
|
|
||||||
} // namespace obsffmpeg
|
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
#include "d3d11.hpp"
|
#include "d3d11.hpp"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -26,14 +28,20 @@
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4191)
|
||||||
|
#pragma warning(disable : 4242)
|
||||||
#pragma warning(disable : 4244)
|
#pragma warning(disable : 4244)
|
||||||
|
#pragma warning(disable : 4365)
|
||||||
|
#pragma warning(disable : 4986)
|
||||||
#include <graphics/graphics.h>
|
#include <graphics/graphics.h>
|
||||||
#include <libavutil/hwcontext_d3d11va.h>
|
#include <libavutil/hwcontext_d3d11va.h>
|
||||||
#include <obs.h>
|
#include <obs.h>
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
}
|
}
|
||||||
|
|
||||||
obsffmpeg::hwapi::d3d11::d3d11() : _dxgi_module(0), _d3d11_module(0)
|
using namespace ffmpeg::hwapi;
|
||||||
|
|
||||||
|
d3d11::d3d11() : _dxgi_module(0), _d3d11_module(0)
|
||||||
{
|
{
|
||||||
_dxgi_module = LoadLibraryW(L"dxgi.dll");
|
_dxgi_module = LoadLibraryW(L"dxgi.dll");
|
||||||
if (!_dxgi_module)
|
if (!_dxgi_module)
|
||||||
|
@ -43,10 +51,12 @@ obsffmpeg::hwapi::d3d11::d3d11() : _dxgi_module(0), _d3d11_module(0)
|
||||||
if (!_d3d11_module)
|
if (!_d3d11_module)
|
||||||
throw std::runtime_error("Unable to load D3D11");
|
throw std::runtime_error("Unable to load D3D11");
|
||||||
|
|
||||||
_CreateDXGIFactory = reinterpret_cast<CreateDXGIFactory_t>(GetProcAddress(_dxgi_module, "CreateDXGIFactory"));
|
#pragma warning(push)
|
||||||
_CreateDXGIFactory1 =
|
#pragma warning(disable : 4191)
|
||||||
reinterpret_cast<CreateDXGIFactory1_t>(GetProcAddress(_dxgi_module, "CreateDXGIFactory1"));
|
_CreateDXGIFactory = reinterpret_cast<CreateDXGIFactory_t>(GetProcAddress(_dxgi_module, "CreateDXGIFactory"));
|
||||||
_D3D11CreateDevice = reinterpret_cast<D3D11CreateDevice_t>(GetProcAddress(_d3d11_module, "D3D11CreateDevice"));
|
_CreateDXGIFactory1 = reinterpret_cast<CreateDXGIFactory1_t>(GetProcAddress(_dxgi_module, "CreateDXGIFactory1"));
|
||||||
|
_D3D11CreateDevice = reinterpret_cast<D3D11CreateDevice_t>(GetProcAddress(_d3d11_module, "D3D11CreateDevice"));
|
||||||
|
#pragma warning(pop)
|
||||||
|
|
||||||
if (!_CreateDXGIFactory && !_CreateDXGIFactory1)
|
if (!_CreateDXGIFactory && !_CreateDXGIFactory1)
|
||||||
throw std::runtime_error("DXGI not supported");
|
throw std::runtime_error("DXGI not supported");
|
||||||
|
@ -62,13 +72,13 @@ obsffmpeg::hwapi::d3d11::d3d11() : _dxgi_module(0), _d3d11_module(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
obsffmpeg::hwapi::d3d11::~d3d11()
|
d3d11::~d3d11()
|
||||||
{
|
{
|
||||||
FreeLibrary(_dxgi_module);
|
FreeLibrary(_dxgi_module);
|
||||||
FreeLibrary(_d3d11_module);
|
FreeLibrary(_d3d11_module);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<obsffmpeg::hwapi::device> obsffmpeg::hwapi::d3d11::enumerate_adapters()
|
std::list<device> d3d11::enumerate_adapters()
|
||||||
{
|
{
|
||||||
std::list<device> adapters;
|
std::list<device> adapters;
|
||||||
|
|
||||||
|
@ -79,8 +89,8 @@ std::list<obsffmpeg::hwapi::device> obsffmpeg::hwapi::d3d11::enumerate_adapters(
|
||||||
dxgi_adapter->GetDesc1(&desc);
|
dxgi_adapter->GetDesc1(&desc);
|
||||||
|
|
||||||
std::vector<char> buf(1024);
|
std::vector<char> buf(1024);
|
||||||
size_t len = snprintf(buf.data(), buf.size(), "%ls (VEN_%04x/DEV_%04x/SUB_%04x/REV_%04x)",
|
size_t len = snprintf(buf.data(), buf.size(), "%ls (VEN_%04x/DEV_%04x/SUB_%04x/REV_%04x)", desc.Description,
|
||||||
desc.Description, desc.VendorId, desc.DeviceId, desc.SubSysId, desc.Revision);
|
desc.VendorId, desc.DeviceId, desc.SubSysId, desc.Revision);
|
||||||
|
|
||||||
device dev;
|
device dev;
|
||||||
dev.name = std::string(buf.data(), buf.data() + len);
|
dev.name = std::string(buf.data(), buf.data() + len);
|
||||||
|
@ -93,7 +103,7 @@ std::list<obsffmpeg::hwapi::device> obsffmpeg::hwapi::d3d11::enumerate_adapters(
|
||||||
return std::move(adapters);
|
return std::move(adapters);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<obsffmpeg::hwapi::instance> obsffmpeg::hwapi::d3d11::create(obsffmpeg::hwapi::device target)
|
std::shared_ptr<instance> d3d11::create(device target)
|
||||||
{
|
{
|
||||||
std::shared_ptr<d3d11_instance> inst;
|
std::shared_ptr<d3d11_instance> inst;
|
||||||
ATL::CComPtr<ID3D11Device> device;
|
ATL::CComPtr<ID3D11Device> device;
|
||||||
|
@ -115,27 +125,27 @@ std::shared_ptr<obsffmpeg::hwapi::instance> obsffmpeg::hwapi::d3d11::create(obsf
|
||||||
// Create a D3D11 Device
|
// Create a D3D11 Device
|
||||||
UINT device_flags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
|
UINT device_flags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
|
||||||
std::vector<D3D_FEATURE_LEVEL> feature_levels = {D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0,
|
std::vector<D3D_FEATURE_LEVEL> feature_levels = {D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0,
|
||||||
D3D_FEATURE_LEVEL_11_1};
|
D3D_FEATURE_LEVEL_11_1};
|
||||||
|
|
||||||
if (FAILED(_D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_HARDWARE, NULL, device_flags, feature_levels.data(),
|
if (FAILED(_D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_HARDWARE, NULL, device_flags, feature_levels.data(),
|
||||||
static_cast<UINT>(feature_levels.size()), D3D11_SDK_VERSION, &device, NULL,
|
static_cast<UINT>(feature_levels.size()), D3D11_SDK_VERSION, &device, NULL,
|
||||||
&context))) {
|
&context))) {
|
||||||
throw std::runtime_error("Failed to create D3D11 device for target.");
|
throw std::runtime_error("Failed to create D3D11 device for target.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_shared<d3d11_instance>(device, context);
|
return std::make_shared<d3d11_instance>(device, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<obsffmpeg::hwapi::instance> obsffmpeg::hwapi::d3d11::create_from_obs()
|
std::shared_ptr<instance> d3d11::create_from_obs()
|
||||||
{
|
{
|
||||||
auto gctx = obsffmpeg::obs_graphics();
|
auto gctx = util::obs_graphics();
|
||||||
|
|
||||||
if (GS_DEVICE_DIRECT3D_11 != gs_get_device_type()) {
|
if (GS_DEVICE_DIRECT3D_11 != gs_get_device_type()) {
|
||||||
throw std::runtime_error("OBS Device is not a D3D11 Device.");
|
throw std::runtime_error("OBS Device is not a D3D11 Device.");
|
||||||
}
|
}
|
||||||
|
|
||||||
ATL::CComPtr<ID3D11Device> device =
|
ATL::CComPtr<ID3D11Device> device =
|
||||||
ATL::CComPtr<ID3D11Device>(reinterpret_cast<ID3D11Device*>(gs_get_device_obj()));
|
ATL::CComPtr<ID3D11Device>(reinterpret_cast<ID3D11Device*>(gs_get_device_obj()));
|
||||||
ATL::CComPtr<ID3D11DeviceContext> context;
|
ATL::CComPtr<ID3D11DeviceContext> context;
|
||||||
device->GetImmediateContext(&context);
|
device->GetImmediateContext(&context);
|
||||||
|
|
||||||
|
@ -146,16 +156,15 @@ struct D3D11AVFrame {
|
||||||
ATL::CComPtr<ID3D11Texture2D> handle;
|
ATL::CComPtr<ID3D11Texture2D> handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
obsffmpeg::hwapi::d3d11_instance::d3d11_instance(ATL::CComPtr<ID3D11Device> device,
|
d3d11_instance::d3d11_instance(ATL::CComPtr<ID3D11Device> device, ATL::CComPtr<ID3D11DeviceContext> context)
|
||||||
ATL::CComPtr<ID3D11DeviceContext> context)
|
|
||||||
{
|
{
|
||||||
_device = device;
|
_device = device;
|
||||||
_context = context;
|
_context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
obsffmpeg::hwapi::d3d11_instance::~d3d11_instance() {}
|
d3d11_instance::~d3d11_instance() {}
|
||||||
|
|
||||||
AVBufferRef* obsffmpeg::hwapi::d3d11_instance::create_device_context()
|
AVBufferRef* d3d11_instance::create_device_context()
|
||||||
{
|
{
|
||||||
AVBufferRef* dctx_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_D3D11VA);
|
AVBufferRef* dctx_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_D3D11VA);
|
||||||
if (!dctx_ref)
|
if (!dctx_ref)
|
||||||
|
@ -179,9 +188,9 @@ AVBufferRef* obsffmpeg::hwapi::d3d11_instance::create_device_context()
|
||||||
return dctx_ref;
|
return dctx_ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<AVFrame> obsffmpeg::hwapi::d3d11_instance::allocate_frame(AVBufferRef* frames)
|
std::shared_ptr<AVFrame> d3d11_instance::allocate_frame(AVBufferRef* frames)
|
||||||
{
|
{
|
||||||
auto gctx = obsffmpeg::obs_graphics();
|
auto gctx = util::obs_graphics();
|
||||||
|
|
||||||
auto frame = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame* frame) {
|
auto frame = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame* frame) {
|
||||||
av_frame_unref(frame);
|
av_frame_unref(frame);
|
||||||
|
@ -195,16 +204,16 @@ std::shared_ptr<AVFrame> obsffmpeg::hwapi::d3d11_instance::allocate_frame(AVBuff
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
void obsffmpeg::hwapi::d3d11_instance::copy_from_obs(AVBufferRef*, uint32_t handle, uint64_t lock_key,
|
void d3d11_instance::copy_from_obs(AVBufferRef*, uint32_t handle, uint64_t lock_key, uint64_t* next_lock_key,
|
||||||
uint64_t* next_lock_key, std::shared_ptr<AVFrame> frame)
|
std::shared_ptr<AVFrame> frame)
|
||||||
{
|
{
|
||||||
auto gctx = obsffmpeg::obs_graphics();
|
auto gctx = util::obs_graphics();
|
||||||
|
|
||||||
ATL::CComPtr<IDXGIKeyedMutex> mutex;
|
ATL::CComPtr<IDXGIKeyedMutex> mutex;
|
||||||
ATL::CComPtr<ID3D11Texture2D> input;
|
ATL::CComPtr<ID3D11Texture2D> input;
|
||||||
|
|
||||||
if (FAILED(_device->OpenSharedResource(reinterpret_cast<HANDLE>(static_cast<uintptr_t>(handle)),
|
if (FAILED(_device->OpenSharedResource(reinterpret_cast<HANDLE>(static_cast<uintptr_t>(handle)),
|
||||||
__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&input)))) {
|
__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&input)))) {
|
||||||
throw std::runtime_error("Failed to open shared texture resource.");
|
throw std::runtime_error("Failed to open shared texture resource.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,12 +243,14 @@ void obsffmpeg::hwapi::d3d11_instance::copy_from_obs(AVBufferRef*, uint32_t hand
|
||||||
mutex->ReleaseSync(*next_lock_key);
|
mutex->ReleaseSync(*next_lock_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<AVFrame> obsffmpeg::hwapi::d3d11_instance::avframe_from_obs(AVBufferRef* frames, uint32_t handle,
|
std::shared_ptr<AVFrame> d3d11_instance::avframe_from_obs(AVBufferRef* frames, uint32_t handle, uint64_t lock_key,
|
||||||
uint64_t lock_key, uint64_t* next_lock_key)
|
uint64_t* next_lock_key)
|
||||||
{
|
{
|
||||||
auto gctx = obsffmpeg::obs_graphics();
|
auto gctx = util::obs_graphics();
|
||||||
|
|
||||||
auto frame = this->allocate_frame(frames);
|
auto frame = this->allocate_frame(frames);
|
||||||
this->copy_from_obs(frames, handle, lock_key, next_lock_key, frame);
|
this->copy_from_obs(frames, handle, lock_key, next_lock_key, frame);
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -19,62 +19,68 @@
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
|
||||||
|
extern "C++" {
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4191)
|
||||||
|
#pragma warning(disable : 4242)
|
||||||
|
#pragma warning(disable : 4244)
|
||||||
|
#pragma warning(disable : 4365)
|
||||||
|
#pragma warning(disable : 4777)
|
||||||
|
#pragma warning(disable : 4986)
|
||||||
|
#pragma warning(disable : 5039)
|
||||||
#include <atlutil.h>
|
#include <atlutil.h>
|
||||||
#include <d3d11.h>
|
#include <d3d11.h>
|
||||||
#include <d3d11_1.h>
|
#include <d3d11_1.h>
|
||||||
#include <dxgi.h>
|
#include <dxgi.h>
|
||||||
#include "base.hpp"
|
#pragma warning(pop)
|
||||||
|
}
|
||||||
|
|
||||||
namespace obsffmpeg {
|
namespace ffmpeg::hwapi {
|
||||||
namespace hwapi {
|
class d3d11 : public ffmpeg::hwapi::base {
|
||||||
class d3d11 : public ::obsffmpeg::hwapi::base {
|
typedef HRESULT(__stdcall* CreateDXGIFactory_t)(REFIID, void**);
|
||||||
typedef HRESULT(__stdcall* CreateDXGIFactory_t)(REFIID, void**);
|
typedef HRESULT(__stdcall* CreateDXGIFactory1_t)(REFIID, void**);
|
||||||
typedef HRESULT(__stdcall* CreateDXGIFactory1_t)(REFIID, void**);
|
typedef HRESULT(__stdcall* D3D11CreateDevice_t)(IDXGIAdapter*, D3D_DRIVER_TYPE, HMODULE, UINT,
|
||||||
typedef HRESULT(__stdcall* D3D11CreateDevice_t)(_In_opt_ IDXGIAdapter*, D3D_DRIVER_TYPE,
|
CONST D3D_FEATURE_LEVEL*, UINT, UINT, ID3D11Device**,
|
||||||
HMODULE, UINT, CONST D3D_FEATURE_LEVEL*, UINT,
|
D3D_FEATURE_LEVEL*, ID3D11DeviceContext**);
|
||||||
UINT, _Out_opt_ ID3D11Device**,
|
|
||||||
_Out_opt_ D3D_FEATURE_LEVEL*,
|
|
||||||
_Out_opt_ ID3D11DeviceContext**);
|
|
||||||
|
|
||||||
HMODULE _dxgi_module;
|
HMODULE _dxgi_module;
|
||||||
CreateDXGIFactory_t _CreateDXGIFactory;
|
CreateDXGIFactory_t _CreateDXGIFactory;
|
||||||
CreateDXGIFactory1_t _CreateDXGIFactory1;
|
CreateDXGIFactory1_t _CreateDXGIFactory1;
|
||||||
|
|
||||||
HMODULE _d3d11_module;
|
HMODULE _d3d11_module;
|
||||||
D3D11CreateDevice_t _D3D11CreateDevice;
|
D3D11CreateDevice_t _D3D11CreateDevice;
|
||||||
|
|
||||||
ATL::CComPtr<IDXGIFactory1> _dxgifactory;
|
ATL::CComPtr<IDXGIFactory1> _dxgifactory;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
d3d11();
|
d3d11();
|
||||||
virtual ~d3d11();
|
virtual ~d3d11();
|
||||||
|
|
||||||
virtual std::list<obsffmpeg::hwapi::device> enumerate_adapters() override;
|
virtual std::list<hwapi::device> enumerate_adapters() override;
|
||||||
|
|
||||||
virtual std::shared_ptr<obsffmpeg::hwapi::instance>
|
virtual std::shared_ptr<hwapi::instance> create(hwapi::device target) override;
|
||||||
create(obsffmpeg::hwapi::device target) override;
|
|
||||||
|
|
||||||
virtual std::shared_ptr<obsffmpeg::hwapi::instance> create_from_obs() override;
|
virtual std::shared_ptr<hwapi::instance> create_from_obs() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class d3d11_instance : public ::obsffmpeg::hwapi::instance {
|
class d3d11_instance : public ffmpeg::hwapi::instance {
|
||||||
ATL::CComPtr<ID3D11Device> _device;
|
ATL::CComPtr<ID3D11Device> _device;
|
||||||
ATL::CComPtr<ID3D11DeviceContext> _context;
|
ATL::CComPtr<ID3D11DeviceContext> _context;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
d3d11_instance(ATL::CComPtr<ID3D11Device> device, ATL::CComPtr<ID3D11DeviceContext> context);
|
d3d11_instance(ATL::CComPtr<ID3D11Device> device, ATL::CComPtr<ID3D11DeviceContext> context);
|
||||||
virtual ~d3d11_instance();
|
virtual ~d3d11_instance();
|
||||||
|
|
||||||
virtual AVBufferRef* create_device_context() override;
|
virtual AVBufferRef* create_device_context() override;
|
||||||
|
|
||||||
virtual std::shared_ptr<AVFrame> allocate_frame(AVBufferRef* frames) override;
|
virtual std::shared_ptr<AVFrame> allocate_frame(AVBufferRef* frames) override;
|
||||||
|
|
||||||
virtual void copy_from_obs(AVBufferRef* frames, uint32_t handle, uint64_t lock_key,
|
virtual void copy_from_obs(AVBufferRef* frames, uint32_t handle, uint64_t lock_key, uint64_t* next_lock_key,
|
||||||
uint64_t* next_lock_key, std::shared_ptr<AVFrame> frame) override;
|
std::shared_ptr<AVFrame> frame) override;
|
||||||
|
|
||||||
virtual std::shared_ptr<AVFrame> avframe_from_obs(AVBufferRef* frames, uint32_t handle,
|
virtual std::shared_ptr<AVFrame> avframe_from_obs(AVBufferRef* frames, uint32_t handle, uint64_t lock_key,
|
||||||
uint64_t lock_key,
|
uint64_t* next_lock_key) override;
|
||||||
uint64_t* next_lock_key) override;
|
};
|
||||||
};
|
} // namespace ffmpeg::hwapi
|
||||||
} // namespace hwapi
|
|
||||||
} // namespace obsffmpeg
|
|
||||||
|
|
|
@ -22,167 +22,169 @@
|
||||||
#include "swscale.hpp"
|
#include "swscale.hpp"
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
ffmpeg::swscale::swscale() {}
|
using namespace ffmpeg;
|
||||||
|
|
||||||
ffmpeg::swscale::~swscale()
|
swscale::swscale() {}
|
||||||
|
|
||||||
|
swscale::~swscale()
|
||||||
{
|
{
|
||||||
finalize();
|
finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::swscale::set_source_size(uint32_t width, uint32_t height)
|
void swscale::set_source_size(uint32_t width, uint32_t height)
|
||||||
{
|
{
|
||||||
source_size.first = width;
|
source_size.first = width;
|
||||||
source_size.second = height;
|
source_size.second = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::swscale::get_source_size(uint32_t& width, uint32_t& height)
|
void swscale::get_source_size(uint32_t& width, uint32_t& height)
|
||||||
{
|
{
|
||||||
width = this->source_size.first;
|
width = this->source_size.first;
|
||||||
height = this->source_size.second;
|
height = this->source_size.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<uint32_t, uint32_t> ffmpeg::swscale::get_source_size()
|
std::pair<uint32_t, uint32_t> swscale::get_source_size()
|
||||||
{
|
{
|
||||||
return this->source_size;
|
return this->source_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ffmpeg::swscale::get_source_width()
|
uint32_t swscale::get_source_width()
|
||||||
{
|
{
|
||||||
return this->source_size.first;
|
return this->source_size.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ffmpeg::swscale::get_source_height()
|
uint32_t swscale::get_source_height()
|
||||||
{
|
{
|
||||||
return this->source_size.second;
|
return this->source_size.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::swscale::set_source_format(AVPixelFormat format)
|
void swscale::set_source_format(AVPixelFormat format)
|
||||||
{
|
{
|
||||||
source_format = format;
|
source_format = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
AVPixelFormat ffmpeg::swscale::get_source_format()
|
AVPixelFormat swscale::get_source_format()
|
||||||
{
|
{
|
||||||
return this->source_format;
|
return this->source_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::swscale::set_source_color(bool full_range, AVColorSpace space)
|
void swscale::set_source_color(bool full_range, AVColorSpace space)
|
||||||
{
|
{
|
||||||
source_full_range = full_range;
|
source_full_range = full_range;
|
||||||
source_colorspace = space;
|
source_colorspace = space;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::swscale::set_source_colorspace(AVColorSpace space)
|
void swscale::set_source_colorspace(AVColorSpace space)
|
||||||
{
|
{
|
||||||
this->source_colorspace = space;
|
this->source_colorspace = space;
|
||||||
}
|
}
|
||||||
|
|
||||||
AVColorSpace ffmpeg::swscale::get_source_colorspace()
|
AVColorSpace swscale::get_source_colorspace()
|
||||||
{
|
{
|
||||||
return this->source_colorspace;
|
return this->source_colorspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::swscale::set_source_full_range(bool full_range)
|
void swscale::set_source_full_range(bool full_range)
|
||||||
{
|
{
|
||||||
this->source_full_range = full_range;
|
this->source_full_range = full_range;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ffmpeg::swscale::is_source_full_range()
|
bool swscale::is_source_full_range()
|
||||||
{
|
{
|
||||||
return this->source_full_range;
|
return this->source_full_range;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::swscale::set_target_size(uint32_t width, uint32_t height)
|
void swscale::set_target_size(uint32_t width, uint32_t height)
|
||||||
{
|
{
|
||||||
target_size.first = width;
|
target_size.first = width;
|
||||||
target_size.second = height;
|
target_size.second = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::swscale::get_target_size(uint32_t& width, uint32_t& height)
|
void swscale::get_target_size(uint32_t& width, uint32_t& height)
|
||||||
{
|
{
|
||||||
width = target_size.first;
|
width = target_size.first;
|
||||||
height = target_size.second;
|
height = target_size.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<uint32_t, uint32_t> ffmpeg::swscale::get_target_size()
|
std::pair<uint32_t, uint32_t> swscale::get_target_size()
|
||||||
{
|
{
|
||||||
return this->target_size;
|
return this->target_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ffmpeg::swscale::get_target_width()
|
uint32_t swscale::get_target_width()
|
||||||
{
|
{
|
||||||
return this->target_size.first;
|
return this->target_size.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ffmpeg::swscale::get_target_height()
|
uint32_t swscale::get_target_height()
|
||||||
{
|
{
|
||||||
return this->target_size.second;
|
return this->target_size.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::swscale::set_target_format(AVPixelFormat format)
|
void swscale::set_target_format(AVPixelFormat format)
|
||||||
{
|
{
|
||||||
target_format = format;
|
target_format = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
AVPixelFormat ffmpeg::swscale::get_target_format()
|
AVPixelFormat swscale::get_target_format()
|
||||||
{
|
{
|
||||||
return this->target_format;
|
return this->target_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::swscale::set_target_color(bool full_range, AVColorSpace space)
|
void swscale::set_target_color(bool full_range, AVColorSpace space)
|
||||||
{
|
{
|
||||||
target_full_range = full_range;
|
target_full_range = full_range;
|
||||||
target_colorspace = space;
|
target_colorspace = space;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::swscale::set_target_colorspace(AVColorSpace space)
|
void swscale::set_target_colorspace(AVColorSpace space)
|
||||||
{
|
{
|
||||||
this->target_colorspace = space;
|
this->target_colorspace = space;
|
||||||
}
|
}
|
||||||
|
|
||||||
AVColorSpace ffmpeg::swscale::get_target_colorspace()
|
AVColorSpace swscale::get_target_colorspace()
|
||||||
{
|
{
|
||||||
return this->target_colorspace;
|
return this->target_colorspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::swscale::set_target_full_range(bool full_range)
|
void swscale::set_target_full_range(bool full_range)
|
||||||
{
|
{
|
||||||
this->target_full_range = full_range;
|
this->target_full_range = full_range;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ffmpeg::swscale::is_target_full_range()
|
bool swscale::is_target_full_range()
|
||||||
{
|
{
|
||||||
return this->target_full_range;
|
return this->target_full_range;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ffmpeg::swscale::initialize(int flags)
|
bool swscale::initialize(int flags)
|
||||||
{
|
{
|
||||||
if (this->context) {
|
if (this->context) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (source_size.first == 0 || source_size.second == 0 || source_format == AV_PIX_FMT_NONE
|
if (source_size.first == 0 || source_size.second == 0 || source_format == AV_PIX_FMT_NONE
|
||||||
|| source_colorspace == AVCOL_SPC_UNSPECIFIED) {
|
|| source_colorspace == AVCOL_SPC_UNSPECIFIED) {
|
||||||
throw std::invalid_argument("not all source parameters were set");
|
throw std::invalid_argument("not all source parameters were set");
|
||||||
}
|
}
|
||||||
if (target_size.first == 0 || target_size.second == 0 || target_format == AV_PIX_FMT_NONE
|
if (target_size.first == 0 || target_size.second == 0 || target_format == AV_PIX_FMT_NONE
|
||||||
|| target_colorspace == AVCOL_SPC_UNSPECIFIED) {
|
|| target_colorspace == AVCOL_SPC_UNSPECIFIED) {
|
||||||
throw std::invalid_argument("not all target parameters were set");
|
throw std::invalid_argument("not all target parameters were set");
|
||||||
}
|
}
|
||||||
|
|
||||||
this->context = sws_getContext(source_size.first, source_size.second, source_format, target_size.first,
|
this->context = sws_getContext(source_size.first, source_size.second, source_format, target_size.first,
|
||||||
target_size.second, target_format, flags, nullptr, nullptr, nullptr);
|
target_size.second, target_format, flags, nullptr, nullptr, nullptr);
|
||||||
if (!this->context) {
|
if (!this->context) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sws_setColorspaceDetails(this->context, sws_getCoefficients(source_colorspace), source_full_range ? 1 : 0,
|
sws_setColorspaceDetails(this->context, sws_getCoefficients(source_colorspace), source_full_range ? 1 : 0,
|
||||||
sws_getCoefficients(target_colorspace), target_full_range ? 1 : 0, 1L << 16 | 0L,
|
sws_getCoefficients(target_colorspace), target_full_range ? 1 : 0, 1L << 16 | 0L,
|
||||||
1L << 16 | 0L, 1L << 16 | 0L);
|
1L << 16 | 0L, 1L << 16 | 0L);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ffmpeg::swscale::finalize()
|
bool swscale::finalize()
|
||||||
{
|
{
|
||||||
if (this->context) {
|
if (this->context) {
|
||||||
sws_freeContext(this->context);
|
sws_freeContext(this->context);
|
||||||
|
@ -192,13 +194,13 @@ bool ffmpeg::swscale::finalize()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ffmpeg::swscale::convert(const uint8_t* const source_data[], const int source_stride[], int32_t source_row,
|
int32_t swscale::convert(const uint8_t* const source_data[], const int source_stride[], int32_t source_row,
|
||||||
int32_t source_rows, uint8_t* const target_data[], const int target_stride[])
|
int32_t source_rows, uint8_t* const target_data[], const int target_stride[])
|
||||||
{
|
{
|
||||||
if (!this->context) {
|
if (!this->context) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int height =
|
int height =
|
||||||
sws_scale(this->context, source_data, source_stride, source_row, source_rows, target_data, target_stride);
|
sws_scale(this->context, source_data, source_stride, source_row, source_rows, target_data, target_stride);
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,7 @@
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
|
|
||||||
#ifndef OBS_FFMPEG_FFMPEG_SWSCALE
|
|
||||||
#define OBS_FFMPEG_FFMPEG_SWSCALE
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
@ -82,8 +79,6 @@ namespace ffmpeg {
|
||||||
bool finalize();
|
bool finalize();
|
||||||
|
|
||||||
int32_t convert(const uint8_t* const source_data[], const int source_stride[], int32_t source_row,
|
int32_t convert(const uint8_t* const source_data[], const int source_stride[], int32_t source_row,
|
||||||
int32_t source_rows, uint8_t* const target_data[], const int target_stride[]);
|
int32_t source_rows, uint8_t* const target_data[], const int target_stride[]);
|
||||||
};
|
};
|
||||||
} // namespace ffmpeg
|
} // namespace ffmpeg
|
||||||
|
|
||||||
#endif OBS_FFMPEG_FFMPEG_SWSCALE
|
|
||||||
|
|
|
@ -37,26 +37,28 @@ extern "C" {
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ffmpeg::tools::translate_encoder_capabilities(int capabilities)
|
using namespace ffmpeg;
|
||||||
|
|
||||||
|
std::string tools::translate_encoder_capabilities(int capabilities)
|
||||||
{
|
{
|
||||||
// Sorted by relative importance.
|
// Sorted by relative importance.
|
||||||
std::pair<int, std::string> caps[] = {
|
std::pair<int, std::string> caps[] = {
|
||||||
{AV_CODEC_CAP_EXPERIMENTAL, "Experimental"},
|
{AV_CODEC_CAP_EXPERIMENTAL, "Experimental"},
|
||||||
|
|
||||||
// Quality
|
// Quality
|
||||||
{AV_CODEC_CAP_LOSSLESS, "Lossless"},
|
{AV_CODEC_CAP_LOSSLESS, "Lossless"},
|
||||||
|
|
||||||
// Features
|
// Features
|
||||||
{AV_CODEC_CAP_PARAM_CHANGE, "Dynamic Parameter Change"},
|
{AV_CODEC_CAP_PARAM_CHANGE, "Dynamic Parameter Change"},
|
||||||
{AV_CODEC_CAP_SUBFRAMES, "Sub-Frames"},
|
{AV_CODEC_CAP_SUBFRAMES, "Sub-Frames"},
|
||||||
{AV_CODEC_CAP_VARIABLE_FRAME_SIZE, "Variable Frame Size"},
|
{AV_CODEC_CAP_VARIABLE_FRAME_SIZE, "Variable Frame Size"},
|
||||||
{AV_CODEC_CAP_SMALL_LAST_FRAME, "Small Final Frame"},
|
{AV_CODEC_CAP_SMALL_LAST_FRAME, "Small Final Frame"},
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
{AV_CODEC_CAP_TRUNCATED, "Truncated"},
|
{AV_CODEC_CAP_TRUNCATED, "Truncated"},
|
||||||
{AV_CODEC_CAP_CHANNEL_CONF, "AV_CODEC_CAP_CHANNEL_CONF"},
|
{AV_CODEC_CAP_CHANNEL_CONF, "AV_CODEC_CAP_CHANNEL_CONF"},
|
||||||
{AV_CODEC_CAP_DRAW_HORIZ_BAND, "AV_CODEC_CAP_DRAW_HORIZ_BAND"},
|
{AV_CODEC_CAP_DRAW_HORIZ_BAND, "AV_CODEC_CAP_DRAW_HORIZ_BAND"},
|
||||||
{AV_CODEC_CAP_AVOID_PROBING, "AV_CODEC_CAP_AVOID_PROBING"},
|
{AV_CODEC_CAP_AVOID_PROBING, "AV_CODEC_CAP_AVOID_PROBING"},
|
||||||
};
|
};
|
||||||
|
|
||||||
std::stringstream sstr;
|
std::stringstream sstr;
|
||||||
|
@ -75,12 +77,12 @@ std::string ffmpeg::tools::translate_encoder_capabilities(int capabilities)
|
||||||
return sstr.str();
|
return sstr.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* ffmpeg::tools::get_pixel_format_name(AVPixelFormat v)
|
const char* tools::get_pixel_format_name(AVPixelFormat v)
|
||||||
{
|
{
|
||||||
return av_get_pix_fmt_name(v);
|
return av_get_pix_fmt_name(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* ffmpeg::tools::get_color_space_name(AVColorSpace v)
|
const char* tools::get_color_space_name(AVColorSpace v)
|
||||||
{
|
{
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case AVCOL_SPC_RGB:
|
case AVCOL_SPC_RGB:
|
||||||
|
@ -114,7 +116,7 @@ const char* ffmpeg::tools::get_color_space_name(AVColorSpace v)
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* ffmpeg::tools::get_error_description(int error)
|
const char* tools::get_error_description(int error)
|
||||||
{
|
{
|
||||||
thread_local char error_buf[AV_ERROR_MAX_STRING_SIZE + 1];
|
thread_local char error_buf[AV_ERROR_MAX_STRING_SIZE + 1];
|
||||||
if (av_strerror(error, error_buf, AV_ERROR_MAX_STRING_SIZE) < 0) {
|
if (av_strerror(error, error_buf, AV_ERROR_MAX_STRING_SIZE) < 0) {
|
||||||
|
@ -123,26 +125,26 @@ const char* ffmpeg::tools::get_error_description(int error)
|
||||||
return error_buf;
|
return error_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::map<video_format, AVPixelFormat> obs_to_av_format_map = {
|
static std::map<video_format, AVPixelFormat> const obs_to_av_format_map = {
|
||||||
{VIDEO_FORMAT_I420, AV_PIX_FMT_YUV420P}, // YUV 4:2:0
|
{VIDEO_FORMAT_I420, AV_PIX_FMT_YUV420P}, // YUV 4:2:0
|
||||||
{VIDEO_FORMAT_NV12, AV_PIX_FMT_NV12}, // NV12 Packed YUV
|
{VIDEO_FORMAT_NV12, AV_PIX_FMT_NV12}, // NV12 Packed YUV
|
||||||
{VIDEO_FORMAT_YVYU, AV_PIX_FMT_YVYU422}, // YVYU Packed YUV
|
{VIDEO_FORMAT_YVYU, AV_PIX_FMT_YVYU422}, // YVYU Packed YUV
|
||||||
{VIDEO_FORMAT_YUY2, AV_PIX_FMT_YUYV422}, // YUYV Packed YUV
|
{VIDEO_FORMAT_YUY2, AV_PIX_FMT_YUYV422}, // YUYV Packed YUV
|
||||||
{VIDEO_FORMAT_UYVY, AV_PIX_FMT_UYVY422}, // UYVY Packed YUV
|
{VIDEO_FORMAT_UYVY, AV_PIX_FMT_UYVY422}, // UYVY Packed YUV
|
||||||
{VIDEO_FORMAT_RGBA, AV_PIX_FMT_RGBA}, //
|
{VIDEO_FORMAT_RGBA, AV_PIX_FMT_RGBA}, //
|
||||||
{VIDEO_FORMAT_BGRA, AV_PIX_FMT_BGRA}, //
|
{VIDEO_FORMAT_BGRA, AV_PIX_FMT_BGRA}, //
|
||||||
{VIDEO_FORMAT_BGRX, AV_PIX_FMT_BGR0}, //
|
{VIDEO_FORMAT_BGRX, AV_PIX_FMT_BGR0}, //
|
||||||
{VIDEO_FORMAT_Y800, AV_PIX_FMT_GRAY8}, //
|
{VIDEO_FORMAT_Y800, AV_PIX_FMT_GRAY8}, //
|
||||||
{VIDEO_FORMAT_I444, AV_PIX_FMT_YUV444P}, //
|
{VIDEO_FORMAT_I444, AV_PIX_FMT_YUV444P}, //
|
||||||
{VIDEO_FORMAT_BGR3, AV_PIX_FMT_BGR24}, //
|
{VIDEO_FORMAT_BGR3, AV_PIX_FMT_BGR24}, //
|
||||||
{VIDEO_FORMAT_I422, AV_PIX_FMT_YUV422P}, //
|
{VIDEO_FORMAT_I422, AV_PIX_FMT_YUV422P}, //
|
||||||
{VIDEO_FORMAT_I40A, AV_PIX_FMT_YUVA420P}, //
|
{VIDEO_FORMAT_I40A, AV_PIX_FMT_YUVA420P}, //
|
||||||
{VIDEO_FORMAT_I42A, AV_PIX_FMT_YUVA422P}, //
|
{VIDEO_FORMAT_I42A, AV_PIX_FMT_YUVA422P}, //
|
||||||
{VIDEO_FORMAT_YUVA, AV_PIX_FMT_YUVA444P}, //
|
{VIDEO_FORMAT_YUVA, AV_PIX_FMT_YUVA444P}, //
|
||||||
//{VIDEO_FORMAT_AYUV, AV_PIX_FMT_AYUV444P}, //
|
//{VIDEO_FORMAT_AYUV, AV_PIX_FMT_AYUV444P}, //
|
||||||
};
|
};
|
||||||
|
|
||||||
AVPixelFormat ffmpeg::tools::obs_videoformat_to_avpixelformat(video_format v)
|
AVPixelFormat tools::obs_videoformat_to_avpixelformat(video_format v)
|
||||||
{
|
{
|
||||||
auto found = obs_to_av_format_map.find(v);
|
auto found = obs_to_av_format_map.find(v);
|
||||||
if (found != obs_to_av_format_map.end()) {
|
if (found != obs_to_av_format_map.end()) {
|
||||||
|
@ -151,7 +153,7 @@ AVPixelFormat ffmpeg::tools::obs_videoformat_to_avpixelformat(video_format v)
|
||||||
return AV_PIX_FMT_NONE;
|
return AV_PIX_FMT_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
video_format ffmpeg::tools::avpixelformat_to_obs_videoformat(AVPixelFormat v)
|
video_format tools::avpixelformat_to_obs_videoformat(AVPixelFormat v)
|
||||||
{
|
{
|
||||||
for (const auto& kv : obs_to_av_format_map) {
|
for (const auto& kv : obs_to_av_format_map) {
|
||||||
if (kv.second == v)
|
if (kv.second == v)
|
||||||
|
@ -160,13 +162,13 @@ video_format ffmpeg::tools::avpixelformat_to_obs_videoformat(AVPixelFormat v)
|
||||||
return VIDEO_FORMAT_NONE;
|
return VIDEO_FORMAT_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
AVPixelFormat ffmpeg::tools::get_least_lossy_format(const AVPixelFormat* haystack, AVPixelFormat needle)
|
AVPixelFormat tools::get_least_lossy_format(const AVPixelFormat* haystack, AVPixelFormat needle)
|
||||||
{
|
{
|
||||||
int data_loss = 0;
|
int data_loss = 0;
|
||||||
return avcodec_find_best_pix_fmt_of_list(haystack, needle, 0, &data_loss);
|
return avcodec_find_best_pix_fmt_of_list(haystack, needle, 0, &data_loss);
|
||||||
}
|
}
|
||||||
|
|
||||||
AVColorSpace ffmpeg::tools::obs_videocolorspace_to_avcolorspace(video_colorspace v)
|
AVColorSpace tools::obs_videocolorspace_to_avcolorspace(video_colorspace v)
|
||||||
{
|
{
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case VIDEO_CS_DEFAULT:
|
case VIDEO_CS_DEFAULT:
|
||||||
|
@ -178,7 +180,7 @@ AVColorSpace ffmpeg::tools::obs_videocolorspace_to_avcolorspace(video_colorspace
|
||||||
throw std::invalid_argument("unknown color space");
|
throw std::invalid_argument("unknown color space");
|
||||||
}
|
}
|
||||||
|
|
||||||
AVColorRange ffmpeg::tools::obs_videorangetype_to_avcolorrange(video_range_type v)
|
AVColorRange tools::obs_videorangetype_to_avcolorrange(video_range_type v)
|
||||||
{
|
{
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case VIDEO_RANGE_DEFAULT:
|
case VIDEO_RANGE_DEFAULT:
|
||||||
|
@ -190,7 +192,7 @@ AVColorRange ffmpeg::tools::obs_videorangetype_to_avcolorrange(video_range_type
|
||||||
throw std::invalid_argument("unknown range");
|
throw std::invalid_argument("unknown range");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ffmpeg::tools::can_hardware_encode(const AVCodec* codec)
|
bool tools::can_hardware_encode(const AVCodec* codec)
|
||||||
{
|
{
|
||||||
AVPixelFormat hardware_formats[] = {AV_PIX_FMT_D3D11};
|
AVPixelFormat hardware_formats[] = {AV_PIX_FMT_D3D11};
|
||||||
|
|
||||||
|
@ -204,7 +206,7 @@ bool ffmpeg::tools::can_hardware_encode(const AVCodec* codec)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AVPixelFormat> ffmpeg::tools::get_software_formats(const AVPixelFormat* list)
|
std::vector<AVPixelFormat> tools::get_software_formats(const AVPixelFormat* list)
|
||||||
{
|
{
|
||||||
AVPixelFormat hardware_formats[] = {
|
AVPixelFormat hardware_formats[] = {
|
||||||
#if FF_API_VAAPI
|
#if FF_API_VAAPI
|
||||||
|
@ -241,18 +243,18 @@ std::vector<AVPixelFormat> ffmpeg::tools::get_software_formats(const AVPixelForm
|
||||||
return std::move(fmts);
|
return std::move(fmts);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::tools::setup_obs_color(video_colorspace colorspace, video_range_type range, AVCodecContext* context)
|
void tools::setup_obs_color(video_colorspace colorspace, video_range_type range, AVCodecContext* context)
|
||||||
{
|
{
|
||||||
std::map<video_colorspace, std::tuple<AVColorSpace, AVColorPrimaries, AVColorTransferCharacteristic>>
|
std::map<video_colorspace, std::tuple<AVColorSpace, AVColorPrimaries, AVColorTransferCharacteristic>> colorspaces =
|
||||||
colorspaces = {
|
{
|
||||||
{VIDEO_CS_DEFAULT, {AVCOL_SPC_BT470BG, AVCOL_PRI_BT470BG, AVCOL_TRC_SMPTE170M}},
|
{VIDEO_CS_DEFAULT, {AVCOL_SPC_BT470BG, AVCOL_PRI_BT470BG, AVCOL_TRC_SMPTE170M}},
|
||||||
{VIDEO_CS_601, {AVCOL_SPC_BT470BG, AVCOL_PRI_BT470BG, AVCOL_TRC_SMPTE170M}},
|
{VIDEO_CS_601, {AVCOL_SPC_BT470BG, AVCOL_PRI_BT470BG, AVCOL_TRC_SMPTE170M}},
|
||||||
{VIDEO_CS_709, {AVCOL_SPC_BT709, AVCOL_PRI_BT709, AVCOL_TRC_BT709}},
|
{VIDEO_CS_709, {AVCOL_SPC_BT709, AVCOL_PRI_BT709, AVCOL_TRC_BT709}},
|
||||||
};
|
};
|
||||||
std::map<video_range_type, AVColorRange> colorranges = {
|
std::map<video_range_type, AVColorRange> colorranges = {
|
||||||
{VIDEO_RANGE_DEFAULT, AVCOL_RANGE_MPEG},
|
{VIDEO_RANGE_DEFAULT, AVCOL_RANGE_MPEG},
|
||||||
{VIDEO_RANGE_PARTIAL, AVCOL_RANGE_MPEG},
|
{VIDEO_RANGE_PARTIAL, AVCOL_RANGE_MPEG},
|
||||||
{VIDEO_RANGE_FULL, AVCOL_RANGE_JPEG},
|
{VIDEO_RANGE_FULL, AVCOL_RANGE_JPEG},
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -274,7 +276,7 @@ void ffmpeg::tools::setup_obs_color(video_colorspace colorspace, video_range_typ
|
||||||
context->chroma_sample_location = AVCHROMA_LOC_CENTER;
|
context->chroma_sample_location = AVCHROMA_LOC_CENTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* ffmpeg::tools::get_std_compliance_name(int compliance)
|
const char* tools::get_std_compliance_name(int compliance)
|
||||||
{
|
{
|
||||||
switch (compliance) {
|
switch (compliance) {
|
||||||
case FF_COMPLIANCE_VERY_STRICT:
|
case FF_COMPLIANCE_VERY_STRICT:
|
||||||
|
@ -291,7 +293,7 @@ const char* ffmpeg::tools::get_std_compliance_name(int compliance)
|
||||||
return "Invalid";
|
return "Invalid";
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* ffmpeg::tools::get_thread_type_name(int thread_type)
|
const char* tools::get_thread_type_name(int thread_type)
|
||||||
{
|
{
|
||||||
switch (thread_type) {
|
switch (thread_type) {
|
||||||
case FF_THREAD_FRAME | FF_THREAD_SLICE:
|
case FF_THREAD_FRAME | FF_THREAD_SLICE:
|
||||||
|
@ -305,37 +307,36 @@ const char* ffmpeg::tools::get_thread_type_name(int thread_type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::tools::print_av_option_bool(AVCodecContext* context, const char* option, std::string text)
|
void tools::print_av_option_bool(AVCodecContext* context, const char* option, std::string text)
|
||||||
{
|
{
|
||||||
if (av_opt_is_set_to_default_by_name(context, option, AV_OPT_SEARCH_CHILDREN) == 0) {
|
if (av_opt_is_set_to_default_by_name(context, option, AV_OPT_SEARCH_CHILDREN) == 0) {
|
||||||
int64_t v = 0;
|
int64_t v = 0;
|
||||||
if (av_opt_get_int(context, option, AV_OPT_SEARCH_CHILDREN, &v) == 0) {
|
if (av_opt_get_int(context, option, AV_OPT_SEARCH_CHILDREN, &v) == 0) {
|
||||||
PLOG_INFO("[%s] %s: %s", context->codec->name, text.c_str(), v == 0 ? "Disabled" : "Enabled");
|
LOG_INFO("[%s] %s: %s", context->codec->name, text.c_str(), v == 0 ? "Disabled" : "Enabled");
|
||||||
} else {
|
} else {
|
||||||
PLOG_INFO("[%s] %s: <Error>", context->codec->name, text.c_str());
|
LOG_INFO("[%s] %s: <Error>", context->codec->name, text.c_str());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PLOG_INFO("[%s] %s: <Default>", context->codec->name, text.c_str());
|
LOG_INFO("[%s] %s: <Default>", context->codec->name, text.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::tools::print_av_option_int(AVCodecContext* context, const char* option, std::string text,
|
void tools::print_av_option_int(AVCodecContext* context, const char* option, std::string text, std::string suffix)
|
||||||
std::string suffix)
|
|
||||||
{
|
{
|
||||||
if (av_opt_is_set_to_default_by_name(context, option, AV_OPT_SEARCH_CHILDREN) == 0) {
|
if (av_opt_is_set_to_default_by_name(context, option, AV_OPT_SEARCH_CHILDREN) == 0) {
|
||||||
int64_t v = 0;
|
int64_t v = 0;
|
||||||
if (av_opt_get_int(context, option, AV_OPT_SEARCH_CHILDREN, &v) == 0) {
|
if (av_opt_get_int(context, option, AV_OPT_SEARCH_CHILDREN, &v) == 0) {
|
||||||
PLOG_INFO("[%s] %s: %lld %s", context->codec->name, text.c_str(), v, suffix.c_str());
|
LOG_INFO("[%s] %s: %lld %s", context->codec->name, text.c_str(), v, suffix.c_str());
|
||||||
} else {
|
} else {
|
||||||
PLOG_INFO("[%s] %s: <Error>", context->codec->name, text.c_str());
|
LOG_INFO("[%s] %s: <Error>", context->codec->name, text.c_str());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PLOG_INFO("[%s] %s: <Default>", context->codec->name, text.c_str());
|
LOG_INFO("[%s] %s: <Default>", context->codec->name, text.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpeg::tools::print_av_option_string(AVCodecContext* context, const char* option, std::string text,
|
void tools::print_av_option_string(AVCodecContext* context, const char* option, std::string text,
|
||||||
std::function<std::string(int64_t)> decoder)
|
std::function<std::string(int64_t)> decoder)
|
||||||
{
|
{
|
||||||
if (av_opt_is_set_to_default_by_name(context, option, AV_OPT_SEARCH_CHILDREN) == 0) {
|
if (av_opt_is_set_to_default_by_name(context, option, AV_OPT_SEARCH_CHILDREN) == 0) {
|
||||||
int64_t v = 0;
|
int64_t v = 0;
|
||||||
|
@ -343,11 +344,11 @@ void ffmpeg::tools::print_av_option_string(AVCodecContext* context, const char*
|
||||||
std::string name = "<Unknown>";
|
std::string name = "<Unknown>";
|
||||||
if (decoder)
|
if (decoder)
|
||||||
name = decoder(v);
|
name = decoder(v);
|
||||||
PLOG_INFO("[%s] %s: %s", context->codec->name, text.c_str(), name.c_str());
|
LOG_INFO("[%s] %s: %s", context->codec->name, text.c_str(), name.c_str());
|
||||||
} else {
|
} else {
|
||||||
PLOG_INFO("[%s] %s: <Error>", context->codec->name, text.c_str());
|
LOG_INFO("[%s] %s: <Error>", context->codec->name, text.c_str());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PLOG_INFO("[%s] %s: <Default>", context->codec->name, text.c_str());
|
LOG_INFO("[%s] %s: <Default>", context->codec->name, text.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,7 @@
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
|
|
||||||
#ifndef OBS_FFMPEG_FFMPEG_UTILITY
|
|
||||||
#define OBS_FFMPEG_FFMPEG_UTILITY
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <obs.h>
|
#include <obs.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -33,45 +30,40 @@ extern "C" {
|
||||||
#include <libavutil/pixfmt.h>
|
#include <libavutil/pixfmt.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ffmpeg {
|
namespace ffmpeg::tools {
|
||||||
namespace tools {
|
std::string translate_encoder_capabilities(int capabilities);
|
||||||
std::string translate_encoder_capabilities(int capabilities);
|
|
||||||
|
|
||||||
const char* get_pixel_format_name(AVPixelFormat v);
|
const char* get_pixel_format_name(AVPixelFormat v);
|
||||||
|
|
||||||
const char* get_color_space_name(AVColorSpace v);
|
const char* get_color_space_name(AVColorSpace v);
|
||||||
|
|
||||||
const char* get_error_description(int error);
|
const char* get_error_description(int error);
|
||||||
|
|
||||||
AVPixelFormat obs_videoformat_to_avpixelformat(video_format v);
|
AVPixelFormat obs_videoformat_to_avpixelformat(video_format v);
|
||||||
|
|
||||||
video_format avpixelformat_to_obs_videoformat(AVPixelFormat v);
|
video_format avpixelformat_to_obs_videoformat(AVPixelFormat v);
|
||||||
|
|
||||||
AVPixelFormat get_least_lossy_format(const AVPixelFormat* haystack, AVPixelFormat needle);
|
AVPixelFormat get_least_lossy_format(const AVPixelFormat* haystack, AVPixelFormat needle);
|
||||||
|
|
||||||
AVColorSpace obs_videocolorspace_to_avcolorspace(video_colorspace v);
|
AVColorSpace obs_videocolorspace_to_avcolorspace(video_colorspace v);
|
||||||
|
|
||||||
AVColorRange obs_videorangetype_to_avcolorrange(video_range_type v);
|
AVColorRange obs_videorangetype_to_avcolorrange(video_range_type v);
|
||||||
|
|
||||||
bool can_hardware_encode(const AVCodec* codec);
|
bool can_hardware_encode(const AVCodec* codec);
|
||||||
|
|
||||||
std::vector<AVPixelFormat> get_software_formats(const AVPixelFormat* list);
|
std::vector<AVPixelFormat> get_software_formats(const AVPixelFormat* list);
|
||||||
|
|
||||||
void setup_obs_color(video_colorspace colorspace, video_range_type range, AVCodecContext* context);
|
void setup_obs_color(video_colorspace colorspace, video_range_type range, AVCodecContext* context);
|
||||||
|
|
||||||
const char* get_std_compliance_name(int compliance);
|
const char* get_std_compliance_name(int compliance);
|
||||||
|
|
||||||
const char* get_thread_type_name(int thread_type);
|
const char* get_thread_type_name(int thread_type);
|
||||||
|
|
||||||
void print_av_option_bool(AVCodecContext* context, const char* option, std::string text);
|
void print_av_option_bool(AVCodecContext* context, const char* option, std::string text);
|
||||||
|
|
||||||
void print_av_option_int(AVCodecContext* context, const char* option, std::string text,
|
void print_av_option_int(AVCodecContext* context, const char* option, std::string text, std::string suffix);
|
||||||
std::string suffix);
|
|
||||||
|
|
||||||
void print_av_option_string(AVCodecContext* context, const char* option, std::string text,
|
void print_av_option_string(AVCodecContext* context, const char* option, std::string text,
|
||||||
std::function<std::string(int64_t)> decoder);
|
std::function<std::string(int64_t)> decoder);
|
||||||
|
|
||||||
} // namespace tools
|
} // namespace ffmpeg::tools
|
||||||
} // namespace ffmpeg
|
|
||||||
|
|
||||||
#endif OBS_FFMPEG_FFMPEG_UTILITY
|
|
||||||
|
|
|
@ -77,6 +77,8 @@
|
||||||
#define ST_MASK_ALPHA "Filter.Blur.Mask.Alpha"
|
#define ST_MASK_ALPHA "Filter.Blur.Mask.Alpha"
|
||||||
#define ST_MASK_MULTIPLIER "Filter.Blur.Mask.Multiplier"
|
#define ST_MASK_MULTIPLIER "Filter.Blur.Mask.Multiplier"
|
||||||
|
|
||||||
|
using namespace filter;
|
||||||
|
|
||||||
struct local_blur_type_t {
|
struct local_blur_type_t {
|
||||||
std::function<::gfx::blur::ifactory&()> fn;
|
std::function<::gfx::blur::ifactory&()> fn;
|
||||||
const char* name;
|
const char* name;
|
||||||
|
@ -100,9 +102,9 @@ static std::map<std::string, local_blur_subtype_t> list_of_subtypes = {
|
||||||
{"zoom", {::gfx::blur::type::Zoom, S_BLUR_SUBTYPE_ZOOM}},
|
{"zoom", {::gfx::blur::type::Zoom, S_BLUR_SUBTYPE_ZOOM}},
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<filter::blur::blur_factory> filter::blur::blur_factory::factory_instance = nullptr;
|
std::shared_ptr<blur::blur_factory> blur::blur_factory::factory_instance = nullptr;
|
||||||
|
|
||||||
filter::blur::blur_instance::blur_instance(obs_data_t* settings, obs_source_t* self)
|
blur::blur_instance::blur_instance(obs_data_t* settings, obs_source_t* self)
|
||||||
: obs::source_instance(settings, self), _source_rendered(false), _output_rendered(false)
|
: obs::source_instance(settings, self), _source_rendered(false), _output_rendered(false)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
@ -118,7 +120,7 @@ filter::blur::blur_instance::blur_instance(obs_data_t* settings, obs_source_t* s
|
||||||
try {
|
try {
|
||||||
_effect_mask = gs::effect::create(file);
|
_effect_mask = gs::effect::create(file);
|
||||||
} catch (std::runtime_error& ex) {
|
} catch (std::runtime_error& ex) {
|
||||||
P_LOG_ERROR("<filter-blur> Loading _effect '%s' failed with error(s): %s", file, ex.what());
|
LOG_ERROR("<filter-blur> Loading _effect '%s' failed with error(s): %s", file, ex.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
bfree(file);
|
bfree(file);
|
||||||
|
@ -128,10 +130,10 @@ filter::blur::blur_instance::blur_instance(obs_data_t* settings, obs_source_t* s
|
||||||
update(settings);
|
update(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
filter::blur::blur_instance::~blur_instance() {}
|
blur::blur_instance::~blur_instance() {}
|
||||||
|
|
||||||
bool filter::blur::blur_instance::apply_mask_parameters(gs::effect effect, gs_texture_t* original_texture,
|
bool blur::blur_instance::apply_mask_parameters(gs::effect effect, gs_texture_t* original_texture,
|
||||||
gs_texture_t* blurred_texture)
|
gs_texture_t* blurred_texture)
|
||||||
{
|
{
|
||||||
if (effect.has_parameter("image_orig")) {
|
if (effect.has_parameter("image_orig")) {
|
||||||
effect.get_parameter("image_orig").set_texture(original_texture);
|
effect.get_parameter("image_orig").set_texture(original_texture);
|
||||||
|
@ -235,10 +237,10 @@ inline void migrate_settings(obs_data_t* settings)
|
||||||
obs_data_unset_user_value(settings, "Filter.Blur.Directional.Angle");
|
obs_data_unset_user_value(settings, "Filter.Blur.Directional.Angle");
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_data_set_int(settings, S_VERSION, STREAMEFFECTS_VERSION);
|
obs_data_set_int(settings, S_VERSION, STREAMFX_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::blur::blur_instance::update(obs_data_t* settings)
|
void blur::blur_instance::update(obs_data_t* settings)
|
||||||
{
|
{
|
||||||
// Ensure backwards compatibility.
|
// Ensure backwards compatibility.
|
||||||
migrate_settings(settings);
|
migrate_settings(settings);
|
||||||
|
@ -276,7 +278,7 @@ void filter::blur::blur_instance::update(obs_data_t* settings)
|
||||||
{ // Masking
|
{ // Masking
|
||||||
_mask.enabled = obs_data_get_bool(settings, ST_MASK);
|
_mask.enabled = obs_data_get_bool(settings, ST_MASK);
|
||||||
if (_mask.enabled) {
|
if (_mask.enabled) {
|
||||||
_mask.type = static_cast<filter::blur::mask_type>(obs_data_get_int(settings, ST_MASK_TYPE));
|
_mask.type = static_cast<blur::mask_type>(obs_data_get_int(settings, ST_MASK_TYPE));
|
||||||
switch (_mask.type) {
|
switch (_mask.type) {
|
||||||
case mask_type::Region:
|
case mask_type::Region:
|
||||||
_mask.region.left = float_t(obs_data_get_double(settings, ST_MASK_REGION_LEFT) / 100.0);
|
_mask.region.left = float_t(obs_data_get_double(settings, ST_MASK_REGION_LEFT) / 100.0);
|
||||||
|
@ -307,12 +309,12 @@ void filter::blur::blur_instance::update(obs_data_t* settings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::blur::blur_instance::load(obs_data_t* settings)
|
void blur::blur_instance::load(obs_data_t* settings)
|
||||||
{
|
{
|
||||||
update(settings);
|
update(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::blur::blur_instance::video_tick(float)
|
void blur::blur_instance::video_tick(float)
|
||||||
{
|
{
|
||||||
// Blur
|
// Blur
|
||||||
if (_blur) {
|
if (_blur) {
|
||||||
|
@ -340,8 +342,8 @@ void filter::blur::blur_instance::video_tick(float)
|
||||||
_mask.image.texture = std::make_shared<gs::texture>(_mask.image.path);
|
_mask.image.texture = std::make_shared<gs::texture>(_mask.image.path);
|
||||||
_mask.image.path_old = _mask.image.path;
|
_mask.image.path_old = _mask.image.path;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("<filter-blur> Instance '%s' failed to load image '%s'.", obs_source_get_name(_self),
|
LOG_ERROR("<filter-blur> Instance '%s' failed to load image '%s'.", obs_source_get_name(_self),
|
||||||
_mask.image.path.c_str());
|
_mask.image.path.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (_mask.type == mask_type::Source) {
|
} else if (_mask.type == mask_type::Source) {
|
||||||
|
@ -351,8 +353,8 @@ void filter::blur::blur_instance::video_tick(float)
|
||||||
_mask.source.is_scene = (obs_scene_from_source(_mask.source.source_texture->get_object()) != nullptr);
|
_mask.source.is_scene = (obs_scene_from_source(_mask.source.source_texture->get_object()) != nullptr);
|
||||||
_mask.source.name_old = _mask.source.name;
|
_mask.source.name_old = _mask.source.name;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("<filter-blur> Instance '%s' failed to grab source '%s'.", obs_source_get_name(_self),
|
LOG_ERROR("<filter-blur> Instance '%s' failed to grab source '%s'.", obs_source_get_name(_self),
|
||||||
_mask.source.name.c_str());
|
_mask.source.name.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -361,7 +363,7 @@ void filter::blur::blur_instance::video_tick(float)
|
||||||
_output_rendered = false;
|
_output_rendered = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
void blur::blur_instance::video_render(gs_effect_t* effect)
|
||||||
{
|
{
|
||||||
obs_source_t* parent = obs_filter_get_parent(this->_self);
|
obs_source_t* parent = obs_filter_get_parent(this->_self);
|
||||||
obs_source_t* target = obs_filter_get_target(this->_self);
|
obs_source_t* target = obs_filter_get_target(this->_self);
|
||||||
|
@ -529,7 +531,7 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
||||||
|
|
||||||
gs_eparam_t* param = gs_effect_get_param_by_name(finalEffect, "image");
|
gs_eparam_t* param = gs_effect_get_param_by_name(finalEffect, "image");
|
||||||
if (!param) {
|
if (!param) {
|
||||||
P_LOG_ERROR("<filter-blur:%s> Failed to set image param.", obs_source_get_name(this->_self));
|
LOG_ERROR("<filter-blur:%s> Failed to set image param.", obs_source_get_name(this->_self));
|
||||||
obs_source_skip_video_filter(_self);
|
obs_source_skip_video_filter(_self);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@ -541,7 +543,7 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
filter::blur::blur_factory::blur_factory()
|
blur::blur_factory::blur_factory()
|
||||||
{
|
{
|
||||||
_info.id = "obs-stream-effects-filter-blur";
|
_info.id = "obs-stream-effects-filter-blur";
|
||||||
_info.type = OBS_SOURCE_TYPE_FILTER;
|
_info.type = OBS_SOURCE_TYPE_FILTER;
|
||||||
|
@ -551,14 +553,14 @@ filter::blur::blur_factory::blur_factory()
|
||||||
finish_setup();
|
finish_setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
filter::blur::blur_factory::~blur_factory() {}
|
blur::blur_factory::~blur_factory() {}
|
||||||
|
|
||||||
const char* filter::blur::blur_factory::get_name()
|
const char* blur::blur_factory::get_name()
|
||||||
{
|
{
|
||||||
return D_TRANSLATE(ST);
|
return D_TRANSLATE(ST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::blur::blur_factory::get_defaults2(obs_data_t* settings)
|
void blur::blur_factory::get_defaults2(obs_data_t* settings)
|
||||||
{
|
{
|
||||||
// Type, Subtype
|
// Type, Subtype
|
||||||
obs_data_set_default_string(settings, ST_TYPE, "box");
|
obs_data_set_default_string(settings, ST_TYPE, "box");
|
||||||
|
@ -731,7 +733,7 @@ try {
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // Masking
|
{ // Masking
|
||||||
using namespace filter::blur;
|
using namespace blur;
|
||||||
bool show_mask = obs_data_get_bool(settings, ST_MASK);
|
bool show_mask = obs_data_get_bool(settings, ST_MASK);
|
||||||
mask_type mtype = static_cast<mask_type>(obs_data_get_int(settings, ST_MASK_TYPE));
|
mask_type mtype = static_cast<mask_type>(obs_data_get_int(settings, ST_MASK_TYPE));
|
||||||
bool show_region = (mtype == mask_type::Region) && show_mask;
|
bool show_region = (mtype == mask_type::Region) && show_mask;
|
||||||
|
@ -754,11 +756,11 @@ try {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in modified_properties callback.");
|
LOG_ERROR("Unexpected exception in modified_properties callback.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_properties_t* filter::blur::blur_factory::get_properties2(filter::blur::blur_instance* data)
|
obs_properties_t* blur::blur_factory::get_properties2(blur::blur_instance* data)
|
||||||
{
|
{
|
||||||
obs_properties_t* pr = obs_properties_create();
|
obs_properties_t* pr = obs_properties_create();
|
||||||
obs_property_t* p = NULL;
|
obs_property_t* p = NULL;
|
||||||
|
@ -877,7 +879,7 @@ obs_properties_t* filter::blur::blur_factory::get_properties2(filter::blur::blur
|
||||||
return pr;
|
return pr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string filter::blur::blur_factory::translate_string(const char* format, ...)
|
std::string blur::blur_factory::translate_string(const char* format, ...)
|
||||||
{
|
{
|
||||||
va_list vargs;
|
va_list vargs;
|
||||||
va_start(vargs, format);
|
va_start(vargs, format);
|
||||||
|
|
|
@ -42,119 +42,116 @@
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace filter {
|
namespace filter::blur {
|
||||||
namespace blur {
|
enum class mask_type : int64_t {
|
||||||
enum class mask_type : int64_t {
|
Region,
|
||||||
Region,
|
Image,
|
||||||
Image,
|
Source,
|
||||||
Source,
|
};
|
||||||
};
|
|
||||||
|
|
||||||
class blur_instance : public obs::source_instance {
|
class blur_instance : public obs::source_instance {
|
||||||
// Effects
|
// Effects
|
||||||
gs::effect _effect_mask;
|
gs::effect _effect_mask;
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
std::shared_ptr<gs::rendertarget> _source_rt;
|
std::shared_ptr<gs::rendertarget> _source_rt;
|
||||||
std::shared_ptr<gs::texture> _source_texture;
|
std::shared_ptr<gs::texture> _source_texture;
|
||||||
bool _source_rendered;
|
bool _source_rendered;
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
std::shared_ptr<gs::texture> _output_texture;
|
std::shared_ptr<gs::texture> _output_texture;
|
||||||
std::shared_ptr<gs::rendertarget> _output_rt;
|
std::shared_ptr<gs::rendertarget> _output_rt;
|
||||||
bool _output_rendered;
|
bool _output_rendered;
|
||||||
|
|
||||||
// Blur
|
// Blur
|
||||||
std::shared_ptr<::gfx::blur::base> _blur;
|
std::shared_ptr<::gfx::blur::base> _blur;
|
||||||
double_t _blur_size;
|
double_t _blur_size;
|
||||||
double_t _blur_angle;
|
double_t _blur_angle;
|
||||||
std::pair<double_t, double_t> _blur_center;
|
std::pair<double_t, double_t> _blur_center;
|
||||||
bool _blur_step_scaling;
|
bool _blur_step_scaling;
|
||||||
std::pair<double_t, double_t> _blur_step_scale;
|
std::pair<double_t, double_t> _blur_step_scale;
|
||||||
|
|
||||||
// Masking
|
// Masking
|
||||||
|
struct {
|
||||||
|
bool enabled;
|
||||||
|
mask_type type;
|
||||||
struct {
|
struct {
|
||||||
bool enabled;
|
float_t left;
|
||||||
mask_type type;
|
float_t top;
|
||||||
struct {
|
float_t right;
|
||||||
float_t left;
|
float_t bottom;
|
||||||
float_t top;
|
float_t feather;
|
||||||
float_t right;
|
float_t feather_shift;
|
||||||
float_t bottom;
|
bool invert;
|
||||||
float_t feather;
|
} region;
|
||||||
float_t feather_shift;
|
struct {
|
||||||
bool invert;
|
std::string path;
|
||||||
} region;
|
std::string path_old;
|
||||||
struct {
|
std::shared_ptr<gs::texture> texture;
|
||||||
std::string path;
|
} image;
|
||||||
std::string path_old;
|
struct {
|
||||||
std::shared_ptr<gs::texture> texture;
|
std::string name_old;
|
||||||
} image;
|
std::string name;
|
||||||
struct {
|
bool is_scene;
|
||||||
std::string name_old;
|
std::shared_ptr<gfx::source_texture> source_texture;
|
||||||
std::string name;
|
std::shared_ptr<gs::texture> texture;
|
||||||
bool is_scene;
|
} source;
|
||||||
std::shared_ptr<gfx::source_texture> source_texture;
|
struct {
|
||||||
std::shared_ptr<gs::texture> texture;
|
float_t r;
|
||||||
} source;
|
float_t g;
|
||||||
struct {
|
float_t b;
|
||||||
float_t r;
|
float_t a;
|
||||||
float_t g;
|
} color;
|
||||||
float_t b;
|
float_t multiplier;
|
||||||
float_t a;
|
} _mask;
|
||||||
} color;
|
|
||||||
float_t multiplier;
|
|
||||||
} _mask;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
blur_instance(obs_data_t* settings, obs_source_t* self);
|
blur_instance(obs_data_t* settings, obs_source_t* self);
|
||||||
~blur_instance();
|
~blur_instance();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void update(obs_data_t* settings) override;
|
virtual void update(obs_data_t* settings) override;
|
||||||
virtual void load(obs_data_t* settings) override;
|
virtual void load(obs_data_t* settings) override;
|
||||||
|
|
||||||
virtual void video_tick(float time) override;
|
virtual void video_tick(float time) override;
|
||||||
virtual void video_render(gs_effect_t* effect) override;
|
virtual void video_render(gs_effect_t* effect) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool apply_mask_parameters(gs::effect effect, gs_texture_t* original_texture,
|
bool apply_mask_parameters(gs::effect effect, gs_texture_t* original_texture, gs_texture_t* blurred_texture);
|
||||||
gs_texture_t* blurred_texture);
|
};
|
||||||
};
|
|
||||||
|
|
||||||
class blur_factory : public obs::source_factory<filter::blur::blur_factory, filter::blur::blur_instance> {
|
class blur_factory : public obs::source_factory<filter::blur::blur_factory, filter::blur::blur_instance> {
|
||||||
static std::shared_ptr<filter::blur::blur_factory> factory_instance;
|
static std::shared_ptr<filter::blur::blur_factory> factory_instance;
|
||||||
|
|
||||||
public: // Singleton
|
public: // Singleton
|
||||||
static void initialize()
|
static void initialize()
|
||||||
{
|
{
|
||||||
factory_instance = std::make_shared<filter::blur::blur_factory>();
|
factory_instance = std::make_shared<filter::blur::blur_factory>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void finalize()
|
static void finalize()
|
||||||
{
|
{
|
||||||
factory_instance.reset();
|
factory_instance.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::shared_ptr<blur_factory> get()
|
static std::shared_ptr<blur_factory> get()
|
||||||
{
|
{
|
||||||
return factory_instance;
|
return factory_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::string> _translation_cache;
|
std::vector<std::string> _translation_cache;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
blur_factory();
|
blur_factory();
|
||||||
virtual ~blur_factory();
|
virtual ~blur_factory();
|
||||||
|
|
||||||
virtual const char* get_name() override;
|
virtual const char* get_name() override;
|
||||||
|
|
||||||
virtual void get_defaults2(obs_data_t* settings) override;
|
virtual void get_defaults2(obs_data_t* settings) override;
|
||||||
|
|
||||||
virtual obs_properties_t* get_properties2(filter::blur::blur_instance* data) override;
|
virtual obs_properties_t* get_properties2(filter::blur::blur_instance* data) override;
|
||||||
|
|
||||||
std::string translate_string(const char* format, ...);
|
std::string translate_string(const char* format, ...);
|
||||||
};
|
};
|
||||||
} // namespace blur
|
} // namespace filter::blur
|
||||||
} // namespace filter
|
|
||||||
|
|
|
@ -74,9 +74,11 @@
|
||||||
#define MODE_LOG Log
|
#define MODE_LOG Log
|
||||||
#define MODE_LOG10 Log10
|
#define MODE_LOG10 Log10
|
||||||
|
|
||||||
filter::color_grade::color_grade_instance::~color_grade_instance() {}
|
using namespace filter;
|
||||||
|
|
||||||
filter::color_grade::color_grade_instance::color_grade_instance(obs_data_t* data, obs_source_t* self)
|
color_grade::color_grade_instance::~color_grade_instance() {}
|
||||||
|
|
||||||
|
color_grade::color_grade_instance::color_grade_instance(obs_data_t* data, obs_source_t* self)
|
||||||
: obs::source_instance(data, self)
|
: obs::source_instance(data, self)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
@ -86,7 +88,7 @@ filter::color_grade::color_grade_instance::color_grade_instance(obs_data_t* data
|
||||||
_effect = gs::effect::create(file);
|
_effect = gs::effect::create(file);
|
||||||
bfree(file);
|
bfree(file);
|
||||||
} catch (std::runtime_error& ex) {
|
} catch (std::runtime_error& ex) {
|
||||||
P_LOG_ERROR("<filter-color-grade> Loading _effect '%s' failed with error(s): %s", file, ex.what());
|
LOG_ERROR("<filter-color-grade> Loading _effect '%s' failed with error(s): %s", file, ex.what());
|
||||||
bfree(file);
|
bfree(file);
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
|
@ -121,12 +123,12 @@ float_t fix_gamma_value(double_t v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::color_grade::color_grade_instance::load(obs_data_t* data)
|
void color_grade::color_grade_instance::load(obs_data_t* data)
|
||||||
{
|
{
|
||||||
update(data);
|
update(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::color_grade::color_grade_instance::update(obs_data_t* data)
|
void color_grade::color_grade_instance::update(obs_data_t* data)
|
||||||
{
|
{
|
||||||
_lift.x = static_cast<float_t>(obs_data_get_double(data, ST_LIFT_(RED)) / 100.0);
|
_lift.x = static_cast<float_t>(obs_data_get_double(data, ST_LIFT_(RED)) / 100.0);
|
||||||
_lift.y = static_cast<float_t>(obs_data_get_double(data, ST_LIFT_(GREEN)) / 100.0);
|
_lift.y = static_cast<float_t>(obs_data_get_double(data, ST_LIFT_(GREEN)) / 100.0);
|
||||||
|
@ -162,13 +164,13 @@ void filter::color_grade::color_grade_instance::update(obs_data_t* data)
|
||||||
_correction.w = static_cast<float_t>(obs_data_get_double(data, ST_CORRECTION_(CONTRAST)) / 100.0);
|
_correction.w = static_cast<float_t>(obs_data_get_double(data, ST_CORRECTION_(CONTRAST)) / 100.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::color_grade::color_grade_instance::video_tick(float)
|
void color_grade::color_grade_instance::video_tick(float)
|
||||||
{
|
{
|
||||||
_source_updated = false;
|
_source_updated = false;
|
||||||
_grade_updated = false;
|
_grade_updated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::color_grade::color_grade_instance::video_render(gs_effect_t* effect)
|
void color_grade::color_grade_instance::video_render(gs_effect_t* effect)
|
||||||
{
|
{
|
||||||
// Grab initial values.
|
// Grab initial values.
|
||||||
obs_source_t* parent = obs_filter_get_parent(_self);
|
obs_source_t* parent = obs_filter_get_parent(_self);
|
||||||
|
@ -252,10 +254,9 @@ void filter::color_grade::color_grade_instance::video_render(gs_effect_t* effect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<filter::color_grade::color_grade_factory> filter::color_grade::color_grade_factory::factory_instance =
|
std::shared_ptr<color_grade::color_grade_factory> color_grade::color_grade_factory::factory_instance = nullptr;
|
||||||
nullptr;
|
|
||||||
|
|
||||||
filter::color_grade::color_grade_factory::color_grade_factory()
|
color_grade::color_grade_factory::color_grade_factory()
|
||||||
{
|
{
|
||||||
_info.id = "obs-stream-effects-filter-color-grade";
|
_info.id = "obs-stream-effects-filter-color-grade";
|
||||||
_info.type = OBS_SOURCE_TYPE_FILTER;
|
_info.type = OBS_SOURCE_TYPE_FILTER;
|
||||||
|
@ -265,14 +266,14 @@ filter::color_grade::color_grade_factory::color_grade_factory()
|
||||||
finish_setup();
|
finish_setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
filter::color_grade::color_grade_factory::~color_grade_factory() {}
|
color_grade::color_grade_factory::~color_grade_factory() {}
|
||||||
|
|
||||||
const char* filter::color_grade::color_grade_factory::get_name()
|
const char* color_grade::color_grade_factory::get_name()
|
||||||
{
|
{
|
||||||
return D_TRANSLATE(ST);
|
return D_TRANSLATE(ST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::color_grade::color_grade_factory::get_defaults2(obs_data_t* data)
|
void color_grade::color_grade_factory::get_defaults2(obs_data_t* data)
|
||||||
{
|
{
|
||||||
obs_data_set_default_string(data, ST_TOOL, ST_CORRECTION);
|
obs_data_set_default_string(data, ST_TOOL, ST_CORRECTION);
|
||||||
obs_data_set_default_double(data, ST_LIFT_(RED), 0);
|
obs_data_set_default_double(data, ST_LIFT_(RED), 0);
|
||||||
|
@ -291,9 +292,8 @@ void filter::color_grade::color_grade_factory::get_defaults2(obs_data_t* data)
|
||||||
obs_data_set_default_double(data, ST_OFFSET_(GREEN), 0.0);
|
obs_data_set_default_double(data, ST_OFFSET_(GREEN), 0.0);
|
||||||
obs_data_set_default_double(data, ST_OFFSET_(BLUE), 0.0);
|
obs_data_set_default_double(data, ST_OFFSET_(BLUE), 0.0);
|
||||||
obs_data_set_default_double(data, ST_OFFSET_(ALL), 0.0);
|
obs_data_set_default_double(data, ST_OFFSET_(ALL), 0.0);
|
||||||
obs_data_set_default_int(data, ST_TINT_MODE, static_cast<int64_t>(filter::color_grade::luma_mode::Linear));
|
obs_data_set_default_int(data, ST_TINT_MODE, static_cast<int64_t>(color_grade::luma_mode::Linear));
|
||||||
obs_data_set_default_int(data, ST_TINT_DETECTION,
|
obs_data_set_default_int(data, ST_TINT_DETECTION, static_cast<int64_t>(color_grade::detection_mode::YUV_SDR));
|
||||||
static_cast<int64_t>(filter::color_grade::detection_mode::YUV_SDR));
|
|
||||||
obs_data_set_default_double(data, ST_TINT_EXPONENT, 1.5);
|
obs_data_set_default_double(data, ST_TINT_EXPONENT, 1.5);
|
||||||
obs_data_set_default_double(data, ST_TINT_(TONE_LOW, RED), 100.0);
|
obs_data_set_default_double(data, ST_TINT_(TONE_LOW, RED), 100.0);
|
||||||
obs_data_set_default_double(data, ST_TINT_(TONE_LOW, GREEN), 100.0);
|
obs_data_set_default_double(data, ST_TINT_(TONE_LOW, GREEN), 100.0);
|
||||||
|
@ -310,7 +310,7 @@ void filter::color_grade::color_grade_factory::get_defaults2(obs_data_t* data)
|
||||||
obs_data_set_default_double(data, ST_CORRECTION_(CONTRAST), 100.0);
|
obs_data_set_default_double(data, ST_CORRECTION_(CONTRAST), 100.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_properties_t* filter::color_grade::color_grade_factory::get_properties2(color_grade_instance* data)
|
obs_properties_t* color_grade::color_grade_factory::get_properties2(color_grade_instance* data)
|
||||||
{
|
{
|
||||||
obs_properties_t* pr = obs_properties_create();
|
obs_properties_t* pr = obs_properties_create();
|
||||||
|
|
||||||
|
@ -400,12 +400,12 @@ obs_properties_t* filter::color_grade::color_grade_factory::get_properties2(colo
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_list(grp, ST_TINT_MODE, D_TRANSLATE(ST_TINT_MODE), OBS_COMBO_TYPE_LIST,
|
auto p = obs_properties_add_list(grp, ST_TINT_MODE, D_TRANSLATE(ST_TINT_MODE), OBS_COMBO_TYPE_LIST,
|
||||||
OBS_COMBO_FORMAT_INT);
|
OBS_COMBO_FORMAT_INT);
|
||||||
std::pair<const char*, filter::color_grade::luma_mode> els[] = {
|
std::pair<const char*, color_grade::luma_mode> els[] = {
|
||||||
{ST_TINT_MODE_(MODE_LINEAR), filter::color_grade::luma_mode::Linear},
|
{ST_TINT_MODE_(MODE_LINEAR), color_grade::luma_mode::Linear},
|
||||||
{ST_TINT_MODE_(MODE_EXP), filter::color_grade::luma_mode::Exp},
|
{ST_TINT_MODE_(MODE_EXP), color_grade::luma_mode::Exp},
|
||||||
{ST_TINT_MODE_(MODE_EXP2), filter::color_grade::luma_mode::Exp2},
|
{ST_TINT_MODE_(MODE_EXP2), color_grade::luma_mode::Exp2},
|
||||||
{ST_TINT_MODE_(MODE_LOG), filter::color_grade::luma_mode::Log},
|
{ST_TINT_MODE_(MODE_LOG), color_grade::luma_mode::Log},
|
||||||
{ST_TINT_MODE_(MODE_LOG10), filter::color_grade::luma_mode::Log10}};
|
{ST_TINT_MODE_(MODE_LOG10), color_grade::luma_mode::Log10}};
|
||||||
for (auto kv : els) {
|
for (auto kv : els) {
|
||||||
obs_property_list_add_int(p, D_TRANSLATE(kv.first), static_cast<int64_t>(kv.second));
|
obs_property_list_add_int(p, D_TRANSLATE(kv.first), static_cast<int64_t>(kv.second));
|
||||||
}
|
}
|
||||||
|
@ -414,10 +414,10 @@ obs_properties_t* filter::color_grade::color_grade_factory::get_properties2(colo
|
||||||
{
|
{
|
||||||
auto p = obs_properties_add_list(grp, ST_TINT_DETECTION, D_TRANSLATE(ST_TINT_DETECTION),
|
auto p = obs_properties_add_list(grp, ST_TINT_DETECTION, D_TRANSLATE(ST_TINT_DETECTION),
|
||||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||||
std::pair<const char*, filter::color_grade::detection_mode> els[] = {
|
std::pair<const char*, color_grade::detection_mode> els[] = {
|
||||||
{ST_TINT_DETECTION_(DETECTION_HSV), filter::color_grade::detection_mode::HSV},
|
{ST_TINT_DETECTION_(DETECTION_HSV), color_grade::detection_mode::HSV},
|
||||||
{ST_TINT_DETECTION_(DETECTION_HSL), filter::color_grade::detection_mode::HSL},
|
{ST_TINT_DETECTION_(DETECTION_HSL), color_grade::detection_mode::HSL},
|
||||||
{ST_TINT_DETECTION_(DETECTION_YUV_SDR), filter::color_grade::detection_mode::YUV_SDR}};
|
{ST_TINT_DETECTION_(DETECTION_YUV_SDR), color_grade::detection_mode::YUV_SDR}};
|
||||||
for (auto kv : els) {
|
for (auto kv : els) {
|
||||||
obs_property_list_add_int(p, D_TRANSLATE(kv.first), static_cast<int64_t>(kv.second));
|
obs_property_list_add_int(p, D_TRANSLATE(kv.first), static_cast<int64_t>(kv.second));
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,88 +27,86 @@
|
||||||
#include "obs/obs-source-factory.hpp"
|
#include "obs/obs-source-factory.hpp"
|
||||||
#include "plugin.hpp"
|
#include "plugin.hpp"
|
||||||
|
|
||||||
namespace filter {
|
namespace filter::color_grade {
|
||||||
namespace color_grade {
|
enum class detection_mode {
|
||||||
enum class detection_mode {
|
HSV,
|
||||||
HSV,
|
HSL,
|
||||||
HSL,
|
YUV_SDR,
|
||||||
YUV_SDR,
|
};
|
||||||
};
|
|
||||||
|
|
||||||
enum class luma_mode {
|
enum class luma_mode {
|
||||||
Linear,
|
Linear,
|
||||||
Exp,
|
Exp,
|
||||||
Exp2,
|
Exp2,
|
||||||
Log,
|
Log,
|
||||||
Log10,
|
Log10,
|
||||||
};
|
};
|
||||||
|
|
||||||
class color_grade_instance : public obs::source_instance {
|
class color_grade_instance : public obs::source_instance {
|
||||||
gs::effect _effect;
|
gs::effect _effect;
|
||||||
|
|
||||||
// Source
|
// Source
|
||||||
std::unique_ptr<gs::rendertarget> _rt_source;
|
std::unique_ptr<gs::rendertarget> _rt_source;
|
||||||
std::shared_ptr<gs::texture> _tex_source;
|
std::shared_ptr<gs::texture> _tex_source;
|
||||||
bool _source_updated;
|
bool _source_updated;
|
||||||
|
|
||||||
// Grading
|
// Grading
|
||||||
std::unique_ptr<gs::rendertarget> _rt_grade;
|
std::unique_ptr<gs::rendertarget> _rt_grade;
|
||||||
std::shared_ptr<gs::texture> _tex_grade;
|
std::shared_ptr<gs::texture> _tex_grade;
|
||||||
bool _grade_updated;
|
bool _grade_updated;
|
||||||
|
|
||||||
// Parameters
|
// Parameters
|
||||||
vec4 _lift;
|
vec4 _lift;
|
||||||
vec4 _gamma;
|
vec4 _gamma;
|
||||||
vec4 _gain;
|
vec4 _gain;
|
||||||
vec4 _offset;
|
vec4 _offset;
|
||||||
detection_mode _tint_detection;
|
detection_mode _tint_detection;
|
||||||
luma_mode _tint_luma;
|
luma_mode _tint_luma;
|
||||||
float_t _tint_exponent;
|
float_t _tint_exponent;
|
||||||
vec3 _tint_low;
|
vec3 _tint_low;
|
||||||
vec3 _tint_mid;
|
vec3 _tint_mid;
|
||||||
vec3 _tint_hig;
|
vec3 _tint_hig;
|
||||||
vec4 _correction;
|
vec4 _correction;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
color_grade_instance(obs_data_t* data, obs_source_t* self);
|
color_grade_instance(obs_data_t* data, obs_source_t* self);
|
||||||
virtual ~color_grade_instance();
|
virtual ~color_grade_instance();
|
||||||
|
|
||||||
virtual void load(obs_data_t* data) override;
|
virtual void load(obs_data_t* data) override;
|
||||||
virtual void update(obs_data_t* data) override;
|
virtual void update(obs_data_t* data) override;
|
||||||
|
|
||||||
virtual void video_tick(float time) override;
|
virtual void video_tick(float time) override;
|
||||||
virtual void video_render(gs_effect_t* effect) override;
|
virtual void video_render(gs_effect_t* effect) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class color_grade_factory : public obs::source_factory<filter::color_grade::color_grade_factory,
|
class color_grade_factory : public obs::source_factory<filter::color_grade::color_grade_factory,
|
||||||
filter::color_grade::color_grade_instance> {
|
filter::color_grade::color_grade_instance> {
|
||||||
static std::shared_ptr<filter::color_grade::color_grade_factory> factory_instance;
|
static std::shared_ptr<filter::color_grade::color_grade_factory> factory_instance;
|
||||||
|
|
||||||
public: // Singleton
|
public: // Singleton
|
||||||
static void initialize()
|
static void initialize()
|
||||||
{
|
{
|
||||||
factory_instance = std::make_shared<filter::color_grade::color_grade_factory>();
|
factory_instance = std::make_shared<filter::color_grade::color_grade_factory>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void finalize()
|
static void finalize()
|
||||||
{
|
{
|
||||||
factory_instance.reset();
|
factory_instance.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::shared_ptr<color_grade_factory> get()
|
static std::shared_ptr<color_grade_factory> get()
|
||||||
{
|
{
|
||||||
return factory_instance;
|
return factory_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
color_grade_factory();
|
color_grade_factory();
|
||||||
virtual ~color_grade_factory();
|
virtual ~color_grade_factory();
|
||||||
|
|
||||||
virtual const char* get_name() override;
|
virtual const char* get_name() override;
|
||||||
|
|
||||||
virtual void get_defaults2(obs_data_t* data) override;
|
virtual void get_defaults2(obs_data_t* data) override;
|
||||||
|
|
||||||
virtual obs_properties_t* get_properties2(color_grade_instance* data) override;
|
virtual obs_properties_t* get_properties2(color_grade_instance* data) override;
|
||||||
};
|
};
|
||||||
} // namespace color_grade
|
} // namespace filter::color_grade
|
||||||
} // namespace filter
|
|
||||||
|
|
|
@ -27,7 +27,9 @@
|
||||||
#define ST_SCALE "Filter.Displacement.Scale"
|
#define ST_SCALE "Filter.Displacement.Scale"
|
||||||
#define ST_SCALE_TYPE "Filter.Displacement.Scale.Type"
|
#define ST_SCALE_TYPE "Filter.Displacement.Scale.Type"
|
||||||
|
|
||||||
filter::displacement::displacement_instance::displacement_instance(obs_data_t* data, obs_source_t* context)
|
using namespace filter;
|
||||||
|
|
||||||
|
displacement::displacement_instance::displacement_instance(obs_data_t* data, obs_source_t* context)
|
||||||
: obs::source_instance(data, context)
|
: obs::source_instance(data, context)
|
||||||
{
|
{
|
||||||
std::string effect = "";
|
std::string effect = "";
|
||||||
|
@ -42,12 +44,12 @@ filter::displacement::displacement_instance::displacement_instance(obs_data_t* d
|
||||||
update(data);
|
update(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
filter::displacement::displacement_instance::~displacement_instance()
|
displacement::displacement_instance::~displacement_instance()
|
||||||
{
|
{
|
||||||
_texture.reset();
|
_texture.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::displacement::displacement_instance::load(obs_data_t* settings)
|
void displacement::displacement_instance::load(obs_data_t* settings)
|
||||||
{
|
{
|
||||||
update(settings);
|
update(settings);
|
||||||
}
|
}
|
||||||
|
@ -56,20 +58,20 @@ inline void migrate_settings(obs_data_t* settings)
|
||||||
{
|
{
|
||||||
uint64_t version = static_cast<uint64_t>(obs_data_get_int(settings, S_VERSION));
|
uint64_t version = static_cast<uint64_t>(obs_data_get_int(settings, S_VERSION));
|
||||||
|
|
||||||
switch (version & STREAMEFFECTS_MASK_COMPAT) {
|
switch (version & STREAMFX_MASK_COMPAT) {
|
||||||
case 0:
|
case 0:
|
||||||
obs_data_set_double(settings, ST_SCALE, obs_data_get_double(settings, "Filter.Displacement.Scale") * 0.5);
|
obs_data_set_double(settings, ST_SCALE, obs_data_get_double(settings, "Filter.Displacement.Scale") * 0.5);
|
||||||
obs_data_set_double(settings, ST_SCALE_TYPE,
|
obs_data_set_double(settings, ST_SCALE_TYPE,
|
||||||
obs_data_get_double(settings, "Filter.Displacement.Ratio") * 100.0);
|
obs_data_get_double(settings, "Filter.Displacement.Ratio") * 100.0);
|
||||||
obs_data_unset_user_value(settings, "Filter.Displacement.Ratio");
|
obs_data_unset_user_value(settings, "Filter.Displacement.Ratio");
|
||||||
case STREAMEFFECTS_MAKE_VERSION(0, 8, 0, 0):
|
case STREAMFX_MAKE_VERSION(0, 8, 0, 0):
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_data_set_int(settings, S_VERSION, STREAMEFFECTS_VERSION);
|
obs_data_set_int(settings, S_VERSION, STREAMFX_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::displacement::displacement_instance::update(obs_data_t* settings)
|
void displacement::displacement_instance::update(obs_data_t* settings)
|
||||||
{
|
{
|
||||||
migrate_settings(settings);
|
migrate_settings(settings);
|
||||||
|
|
||||||
|
@ -87,13 +89,13 @@ void filter::displacement::displacement_instance::update(obs_data_t* settings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::displacement::displacement_instance::video_tick(float_t)
|
void displacement::displacement_instance::video_tick(float_t)
|
||||||
{
|
{
|
||||||
_width = obs_source_get_base_width(_self);
|
_width = obs_source_get_base_width(_self);
|
||||||
_height = obs_source_get_base_height(_self);
|
_height = obs_source_get_base_height(_self);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::displacement::displacement_instance::video_render(gs_effect_t*)
|
void displacement::displacement_instance::video_render(gs_effect_t*)
|
||||||
{
|
{
|
||||||
if (!_texture) { // No displacement map, so just skip us for now.
|
if (!_texture) { // No displacement map, so just skip us for now.
|
||||||
obs_source_skip_video_filter(_self);
|
obs_source_skip_video_filter(_self);
|
||||||
|
@ -115,15 +117,14 @@ void filter::displacement::displacement_instance::video_render(gs_effect_t*)
|
||||||
obs_source_process_filter_end(_self, _effect.get_object(), _width, _height);
|
obs_source_process_filter_end(_self, _effect.get_object(), _width, _height);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string filter::displacement::displacement_instance::get_file()
|
std::string displacement::displacement_instance::get_file()
|
||||||
{
|
{
|
||||||
return _texture_file;
|
return _texture_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<filter::displacement::displacement_factory>
|
std::shared_ptr<displacement::displacement_factory> displacement::displacement_factory::factory_instance = nullptr;
|
||||||
filter::displacement::displacement_factory::factory_instance = nullptr;
|
|
||||||
|
|
||||||
filter::displacement::displacement_factory::displacement_factory()
|
displacement::displacement_factory::displacement_factory()
|
||||||
{
|
{
|
||||||
_info.id = "obs-stream-effects-filter-displacement";
|
_info.id = "obs-stream-effects-filter-displacement";
|
||||||
_info.type = OBS_SOURCE_TYPE_FILTER;
|
_info.type = OBS_SOURCE_TYPE_FILTER;
|
||||||
|
@ -133,14 +134,14 @@ filter::displacement::displacement_factory::displacement_factory()
|
||||||
finish_setup();
|
finish_setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
filter::displacement::displacement_factory::~displacement_factory() {}
|
displacement::displacement_factory::~displacement_factory() {}
|
||||||
|
|
||||||
const char* filter::displacement::displacement_factory::get_name()
|
const char* displacement::displacement_factory::get_name()
|
||||||
{
|
{
|
||||||
return D_TRANSLATE(ST);
|
return D_TRANSLATE(ST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::displacement::displacement_factory::get_defaults2(obs_data_t* data)
|
void displacement::displacement_factory::get_defaults2(obs_data_t* data)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
char* disp = obs_module_file("examples/normal-maps/neutral.png");
|
char* disp = obs_module_file("examples/normal-maps/neutral.png");
|
||||||
|
@ -152,8 +153,7 @@ void filter::displacement::displacement_factory::get_defaults2(obs_data_t* data)
|
||||||
obs_data_set_default_double(data, ST_SCALE_TYPE, 0.0);
|
obs_data_set_default_double(data, ST_SCALE_TYPE, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_properties_t*
|
obs_properties_t* displacement::displacement_factory::get_properties2(displacement::displacement_instance* data)
|
||||||
filter::displacement::displacement_factory::get_properties2(filter::displacement::displacement_instance* data)
|
|
||||||
{
|
{
|
||||||
obs_properties_t* pr = obs_properties_create();
|
obs_properties_t* pr = obs_properties_create();
|
||||||
|
|
||||||
|
|
|
@ -35,63 +35,61 @@
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace filter {
|
namespace filter::displacement {
|
||||||
namespace displacement {
|
class displacement_instance : public obs::source_instance {
|
||||||
class displacement_instance : public obs::source_instance {
|
gs::effect _effect;
|
||||||
gs::effect _effect;
|
|
||||||
|
|
||||||
// Displacement Map
|
// Displacement Map
|
||||||
std::shared_ptr<gs::texture> _texture;
|
std::shared_ptr<gs::texture> _texture;
|
||||||
std::string _texture_file;
|
std::string _texture_file;
|
||||||
float_t _scale[2];
|
float_t _scale[2];
|
||||||
float_t _scale_type;
|
float_t _scale_type;
|
||||||
|
|
||||||
// Cache
|
// Cache
|
||||||
uint32_t _width;
|
uint32_t _width;
|
||||||
uint32_t _height;
|
uint32_t _height;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
displacement_instance(obs_data_t*, obs_source_t*);
|
displacement_instance(obs_data_t*, obs_source_t*);
|
||||||
virtual ~displacement_instance();
|
virtual ~displacement_instance();
|
||||||
|
|
||||||
virtual void load(obs_data_t* settings) override;
|
virtual void load(obs_data_t* settings) override;
|
||||||
virtual void update(obs_data_t* settings) override;
|
virtual void update(obs_data_t* settings) override;
|
||||||
|
|
||||||
virtual void video_tick(float_t) override;
|
virtual void video_tick(float_t) override;
|
||||||
virtual void video_render(gs_effect_t*) override;
|
virtual void video_render(gs_effect_t*) override;
|
||||||
|
|
||||||
std::string get_file();
|
std::string get_file();
|
||||||
};
|
};
|
||||||
|
|
||||||
class displacement_factory : public obs::source_factory<filter::displacement::displacement_factory,
|
class displacement_factory : public obs::source_factory<filter::displacement::displacement_factory,
|
||||||
filter::displacement::displacement_instance> {
|
filter::displacement::displacement_instance> {
|
||||||
static std::shared_ptr<filter::displacement::displacement_factory> factory_instance;
|
static std::shared_ptr<filter::displacement::displacement_factory> factory_instance;
|
||||||
|
|
||||||
public: // Singleton
|
public: // Singleton
|
||||||
static void initialize()
|
static void initialize()
|
||||||
{
|
{
|
||||||
factory_instance = std::make_shared<filter::displacement::displacement_factory>();
|
factory_instance = std::make_shared<filter::displacement::displacement_factory>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void finalize()
|
static void finalize()
|
||||||
{
|
{
|
||||||
factory_instance.reset();
|
factory_instance.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::shared_ptr<displacement_factory> get()
|
static std::shared_ptr<displacement_factory> get()
|
||||||
{
|
{
|
||||||
return factory_instance;
|
return factory_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
displacement_factory();
|
displacement_factory();
|
||||||
virtual ~displacement_factory();
|
virtual ~displacement_factory();
|
||||||
|
|
||||||
virtual const char* get_name() override;
|
virtual const char* get_name() override;
|
||||||
|
|
||||||
virtual void get_defaults2(obs_data_t* data) override;
|
virtual void get_defaults2(obs_data_t* data) override;
|
||||||
|
|
||||||
virtual obs_properties_t* get_properties2(filter::displacement::displacement_instance* data) override;
|
virtual obs_properties_t* get_properties2(filter::displacement::displacement_instance* data) override;
|
||||||
};
|
};
|
||||||
} // namespace displacement
|
} // namespace filter::displacement
|
||||||
} // namespace filter
|
|
||||||
|
|
|
@ -39,17 +39,18 @@
|
||||||
#define ST_CHANNEL_MULTIPLIER "Filter.DynamicMask.Channel.Multiplier"
|
#define ST_CHANNEL_MULTIPLIER "Filter.DynamicMask.Channel.Multiplier"
|
||||||
#define ST_CHANNEL_INPUT "Filter.DynamicMask.Channel.Input"
|
#define ST_CHANNEL_INPUT "Filter.DynamicMask.Channel.Input"
|
||||||
|
|
||||||
std::shared_ptr<filter::dynamic_mask::dynamic_mask_factory>
|
using namespace filter;
|
||||||
filter::dynamic_mask::dynamic_mask_factory::factory_instance = nullptr;
|
|
||||||
|
|
||||||
static std::pair<filter::dynamic_mask::channel, const char*> channel_translations[] = {
|
std::shared_ptr<dynamic_mask::dynamic_mask_factory> dynamic_mask::dynamic_mask_factory::factory_instance = nullptr;
|
||||||
{filter::dynamic_mask::channel::Red, S_CHANNEL_RED},
|
|
||||||
{filter::dynamic_mask::channel::Green, S_CHANNEL_GREEN},
|
static std::pair<dynamic_mask::channel, const char*> channel_translations[] = {
|
||||||
{filter::dynamic_mask::channel::Blue, S_CHANNEL_BLUE},
|
{dynamic_mask::channel::Red, S_CHANNEL_RED},
|
||||||
{filter::dynamic_mask::channel::Alpha, S_CHANNEL_ALPHA},
|
{dynamic_mask::channel::Green, S_CHANNEL_GREEN},
|
||||||
|
{dynamic_mask::channel::Blue, S_CHANNEL_BLUE},
|
||||||
|
{dynamic_mask::channel::Alpha, S_CHANNEL_ALPHA},
|
||||||
};
|
};
|
||||||
|
|
||||||
filter::dynamic_mask::dynamic_mask_instance::dynamic_mask_instance(obs_data_t* settings, obs_source_t* self)
|
dynamic_mask::dynamic_mask_instance::dynamic_mask_instance(obs_data_t* settings, obs_source_t* self)
|
||||||
: obs::source_instance(settings, self), _have_filter_texture(false), _have_input_texture(false),
|
: obs::source_instance(settings, self), _have_filter_texture(false), _have_input_texture(false),
|
||||||
_have_final_texture(false), _precalc(), _effect()
|
_have_final_texture(false), _precalc(), _effect()
|
||||||
{
|
{
|
||||||
|
@ -61,7 +62,7 @@ filter::dynamic_mask::dynamic_mask_instance::dynamic_mask_instance(obs_data_t* s
|
||||||
try {
|
try {
|
||||||
_effect = gs::effect::create(file);
|
_effect = gs::effect::create(file);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Loading channel mask effect failed with error(s):\n%s", ex.what());
|
LOG_ERROR("Loading channel mask effect failed with error(s):\n%s", ex.what());
|
||||||
}
|
}
|
||||||
assert(_effect != nullptr);
|
assert(_effect != nullptr);
|
||||||
bfree(file);
|
bfree(file);
|
||||||
|
@ -70,15 +71,15 @@ filter::dynamic_mask::dynamic_mask_instance::dynamic_mask_instance(obs_data_t* s
|
||||||
update(settings);
|
update(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
filter::dynamic_mask::dynamic_mask_instance::~dynamic_mask_instance() {}
|
dynamic_mask::dynamic_mask_instance::~dynamic_mask_instance() {}
|
||||||
|
|
||||||
void filter::dynamic_mask::dynamic_mask_instance::update(obs_data_t* settings)
|
void dynamic_mask::dynamic_mask_instance::update(obs_data_t* settings)
|
||||||
{
|
{
|
||||||
// Update source.
|
// Update source.
|
||||||
try {
|
try {
|
||||||
_input = std::make_shared<obs::deprecated_source>(obs_data_get_string(settings, ST_INPUT));
|
_input = std::make_shared<obs::deprecated_source>(obs_data_get_string(settings, ST_INPUT));
|
||||||
_input_capture = std::make_shared<gfx::source_texture>(_input, _self);
|
_input_capture = std::make_shared<gfx::source_texture>(_input, _self);
|
||||||
_input->events.rename += std::bind(&filter::dynamic_mask::dynamic_mask_instance::input_renamed, this,
|
_input->events.rename += std::bind(&dynamic_mask::dynamic_mask_instance::input_renamed, this,
|
||||||
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
_input.reset();
|
_input.reset();
|
||||||
|
@ -133,12 +134,12 @@ void filter::dynamic_mask::dynamic_mask_instance::update(obs_data_t* settings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::dynamic_mask::dynamic_mask_instance::load(obs_data_t* settings)
|
void dynamic_mask::dynamic_mask_instance::load(obs_data_t* settings)
|
||||||
{
|
{
|
||||||
update(settings);
|
update(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::dynamic_mask::dynamic_mask_instance::save(obs_data_t* settings)
|
void dynamic_mask::dynamic_mask_instance::save(obs_data_t* settings)
|
||||||
{
|
{
|
||||||
if (_input) {
|
if (_input) {
|
||||||
obs_data_set_string(settings, ST_INPUT, obs_source_get_name(_input->get()));
|
obs_data_set_string(settings, ST_INPUT, obs_source_get_name(_input->get()));
|
||||||
|
@ -169,16 +170,16 @@ void filter::dynamic_mask::dynamic_mask_instance::save(obs_data_t* settings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::dynamic_mask::dynamic_mask_instance::input_renamed(obs::deprecated_source*, std::string old_name,
|
void dynamic_mask::dynamic_mask_instance::input_renamed(obs::deprecated_source*, std::string old_name,
|
||||||
std::string new_name)
|
std::string new_name)
|
||||||
{
|
{
|
||||||
obs_data_t* settings = obs_source_get_settings(_self);
|
obs_data_t* settings = obs_source_get_settings(_self);
|
||||||
obs_data_set_string(settings, ST_INPUT, new_name.c_str());
|
obs_data_set_string(settings, ST_INPUT, new_name.c_str());
|
||||||
obs_source_update(_self, settings);
|
obs_source_update(_self, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool filter::dynamic_mask::dynamic_mask_instance::modified(void*, obs_properties_t* properties, obs_property_t*,
|
bool dynamic_mask::dynamic_mask_instance::modified(void*, obs_properties_t* properties, obs_property_t*,
|
||||||
obs_data_t* settings) noexcept
|
obs_data_t* settings) noexcept
|
||||||
try {
|
try {
|
||||||
channel mask = static_cast<channel>(obs_data_get_int(settings, ST_CHANNEL));
|
channel mask = static_cast<channel>(obs_data_get_int(settings, ST_CHANNEL));
|
||||||
|
|
||||||
|
@ -196,21 +197,21 @@ try {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
return false;
|
return false;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in modified_properties callback.");
|
LOG_ERROR("Unexpected exception in modified_properties callback.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::dynamic_mask::dynamic_mask_instance::video_tick(float)
|
void dynamic_mask::dynamic_mask_instance::video_tick(float)
|
||||||
{
|
{
|
||||||
_have_input_texture = false;
|
_have_input_texture = false;
|
||||||
_have_filter_texture = false;
|
_have_filter_texture = false;
|
||||||
_have_final_texture = false;
|
_have_final_texture = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::dynamic_mask::dynamic_mask_instance::video_render(gs_effect_t* in_effect)
|
void dynamic_mask::dynamic_mask_instance::video_render(gs_effect_t* in_effect)
|
||||||
{
|
{
|
||||||
obs_source_t* parent = obs_filter_get_parent(_self);
|
obs_source_t* parent = obs_filter_get_parent(_self);
|
||||||
obs_source_t* target = obs_filter_get_target(_self);
|
obs_source_t* target = obs_filter_get_target(_self);
|
||||||
|
@ -333,7 +334,7 @@ void filter::dynamic_mask::dynamic_mask_instance::video_render(gs_effect_t* in_e
|
||||||
gs_effect_t* final_effect = in_effect ? in_effect : default_effect;
|
gs_effect_t* final_effect = in_effect ? in_effect : default_effect;
|
||||||
gs_eparam_t* param = gs_effect_get_param_by_name(final_effect, "image");
|
gs_eparam_t* param = gs_effect_get_param_by_name(final_effect, "image");
|
||||||
if (!param) {
|
if (!param) {
|
||||||
P_LOG_ERROR("<filter-dynamic-mask:%s> Failed to set image param.", obs_source_get_name(_self));
|
LOG_ERROR("<filter-dynamic-mask:%s> Failed to set image param.", obs_source_get_name(_self));
|
||||||
obs_source_skip_video_filter(_self);
|
obs_source_skip_video_filter(_self);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@ -345,7 +346,7 @@ void filter::dynamic_mask::dynamic_mask_instance::video_render(gs_effect_t* in_e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
filter::dynamic_mask::dynamic_mask_factory::dynamic_mask_factory()
|
dynamic_mask::dynamic_mask_factory::dynamic_mask_factory()
|
||||||
{
|
{
|
||||||
_info.id = "obs-stream-effects-filter-dynamic-mask";
|
_info.id = "obs-stream-effects-filter-dynamic-mask";
|
||||||
_info.type = OBS_SOURCE_TYPE_FILTER;
|
_info.type = OBS_SOURCE_TYPE_FILTER;
|
||||||
|
@ -355,16 +356,16 @@ filter::dynamic_mask::dynamic_mask_factory::dynamic_mask_factory()
|
||||||
finish_setup();
|
finish_setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
filter::dynamic_mask::dynamic_mask_factory::~dynamic_mask_factory() {}
|
dynamic_mask::dynamic_mask_factory::~dynamic_mask_factory() {}
|
||||||
|
|
||||||
const char* filter::dynamic_mask::dynamic_mask_factory::get_name()
|
const char* dynamic_mask::dynamic_mask_factory::get_name()
|
||||||
{
|
{
|
||||||
return D_TRANSLATE(ST);
|
return D_TRANSLATE(ST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::dynamic_mask::dynamic_mask_factory::get_defaults2(obs_data_t* data)
|
void dynamic_mask::dynamic_mask_factory::get_defaults2(obs_data_t* data)
|
||||||
{
|
{
|
||||||
obs_data_set_default_int(data, ST_CHANNEL, static_cast<int64_t>(filter::dynamic_mask::channel::Red));
|
obs_data_set_default_int(data, ST_CHANNEL, static_cast<int64_t>(dynamic_mask::channel::Red));
|
||||||
for (auto kv : channel_translations) {
|
for (auto kv : channel_translations) {
|
||||||
obs_data_set_default_double(data, (std::string(ST_CHANNEL_VALUE) + "." + kv.second).c_str(), 1.0);
|
obs_data_set_default_double(data, (std::string(ST_CHANNEL_VALUE) + "." + kv.second).c_str(), 1.0);
|
||||||
obs_data_set_default_double(data, (std::string(ST_CHANNEL_MULTIPLIER) + "." + kv.second).c_str(), 1.0);
|
obs_data_set_default_double(data, (std::string(ST_CHANNEL_MULTIPLIER) + "." + kv.second).c_str(), 1.0);
|
||||||
|
@ -375,8 +376,7 @@ void filter::dynamic_mask::dynamic_mask_factory::get_defaults2(obs_data_t* data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_properties_t*
|
obs_properties_t* dynamic_mask::dynamic_mask_factory::get_properties2(dynamic_mask::dynamic_mask_instance* data)
|
||||||
filter::dynamic_mask::dynamic_mask_factory::get_properties2(filter::dynamic_mask::dynamic_mask_instance* data)
|
|
||||||
{
|
{
|
||||||
obs_properties_t* props = obs_properties_create();
|
obs_properties_t* props = obs_properties_create();
|
||||||
obs_property_t* p;
|
obs_property_t* p;
|
||||||
|
@ -446,7 +446,7 @@ obs_properties_t*
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string filter::dynamic_mask::dynamic_mask_factory::translate_string(const char* format, ...)
|
std::string dynamic_mask::dynamic_mask_factory::translate_string(const char* format, ...)
|
||||||
{
|
{
|
||||||
va_list vargs;
|
va_list vargs;
|
||||||
va_start(vargs, format);
|
va_start(vargs, format);
|
||||||
|
|
|
@ -40,92 +40,90 @@
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace filter {
|
namespace filter::dynamic_mask {
|
||||||
namespace dynamic_mask {
|
enum class channel : int8_t { Invalid = -1, Red, Green, Blue, Alpha };
|
||||||
enum class channel : int8_t { Invalid = -1, Red, Green, Blue, Alpha };
|
|
||||||
|
|
||||||
class dynamic_mask_instance : public obs::source_instance {
|
class dynamic_mask_instance : public obs::source_instance {
|
||||||
std::map<std::tuple<channel, channel, std::string>, std::string> _translation_map;
|
std::map<std::tuple<channel, channel, std::string>, std::string> _translation_map;
|
||||||
|
|
||||||
gs::effect _effect;
|
gs::effect _effect;
|
||||||
|
|
||||||
bool _have_filter_texture;
|
bool _have_filter_texture;
|
||||||
std::shared_ptr<gs::rendertarget> _filter_rt;
|
std::shared_ptr<gs::rendertarget> _filter_rt;
|
||||||
std::shared_ptr<gs::texture> _filter_texture;
|
std::shared_ptr<gs::texture> _filter_texture;
|
||||||
|
|
||||||
bool _have_input_texture;
|
bool _have_input_texture;
|
||||||
std::shared_ptr<obs::deprecated_source> _input;
|
std::shared_ptr<obs::deprecated_source> _input;
|
||||||
std::shared_ptr<gfx::source_texture> _input_capture;
|
std::shared_ptr<gfx::source_texture> _input_capture;
|
||||||
std::shared_ptr<gs::texture> _input_texture;
|
std::shared_ptr<gs::texture> _input_texture;
|
||||||
|
|
||||||
bool _have_final_texture;
|
bool _have_final_texture;
|
||||||
std::shared_ptr<gs::rendertarget> _final_rt;
|
std::shared_ptr<gs::rendertarget> _final_rt;
|
||||||
std::shared_ptr<gs::texture> _final_texture;
|
std::shared_ptr<gs::texture> _final_texture;
|
||||||
|
|
||||||
struct channel_data {
|
struct channel_data {
|
||||||
float_t value = 0.0;
|
float_t value = 0.0;
|
||||||
float_t scale = 1.0;
|
float_t scale = 1.0;
|
||||||
vec4 values = {0};
|
vec4 values = {0};
|
||||||
};
|
|
||||||
std::map<channel, channel_data> _channels;
|
|
||||||
|
|
||||||
struct _precalc {
|
|
||||||
vec4 base;
|
|
||||||
vec4 scale;
|
|
||||||
matrix4 matrix;
|
|
||||||
} _precalc;
|
|
||||||
|
|
||||||
public:
|
|
||||||
dynamic_mask_instance(obs_data_t* data, obs_source_t* self);
|
|
||||||
virtual ~dynamic_mask_instance();
|
|
||||||
|
|
||||||
virtual void update(obs_data_t* settings) override;
|
|
||||||
virtual void load(obs_data_t* settings) override;
|
|
||||||
virtual void save(obs_data_t* settings) override;
|
|
||||||
|
|
||||||
void input_renamed(obs::deprecated_source* src, std::string old_name, std::string new_name);
|
|
||||||
|
|
||||||
static bool modified(void* self, obs_properties_t* properties, obs_property_t* property,
|
|
||||||
obs_data_t* settings) noexcept;
|
|
||||||
|
|
||||||
void video_tick(float _time);
|
|
||||||
void video_render(gs_effect_t* effect);
|
|
||||||
};
|
};
|
||||||
|
std::map<channel, channel_data> _channels;
|
||||||
|
|
||||||
class dynamic_mask_factory : public obs::source_factory<filter::dynamic_mask::dynamic_mask_factory,
|
struct _precalc {
|
||||||
filter::dynamic_mask::dynamic_mask_instance> {
|
vec4 base;
|
||||||
static std::shared_ptr<filter::dynamic_mask::dynamic_mask_factory> factory_instance;
|
vec4 scale;
|
||||||
|
matrix4 matrix;
|
||||||
|
} _precalc;
|
||||||
|
|
||||||
public: // Singleton
|
public:
|
||||||
static void initialize()
|
dynamic_mask_instance(obs_data_t* data, obs_source_t* self);
|
||||||
{
|
virtual ~dynamic_mask_instance();
|
||||||
factory_instance = std::make_shared<filter::dynamic_mask::dynamic_mask_factory>();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void finalize()
|
virtual void update(obs_data_t* settings) override;
|
||||||
{
|
virtual void load(obs_data_t* settings) override;
|
||||||
factory_instance.reset();
|
virtual void save(obs_data_t* settings) override;
|
||||||
}
|
|
||||||
|
|
||||||
static std::shared_ptr<dynamic_mask_factory> get()
|
void input_renamed(obs::deprecated_source* src, std::string old_name, std::string new_name);
|
||||||
{
|
|
||||||
return factory_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
static bool modified(void* self, obs_properties_t* properties, obs_property_t* property,
|
||||||
std::list<std::string> _translation_cache;
|
obs_data_t* settings) noexcept;
|
||||||
|
|
||||||
public:
|
void video_tick(float _time);
|
||||||
dynamic_mask_factory();
|
void video_render(gs_effect_t* effect);
|
||||||
virtual ~dynamic_mask_factory() override;
|
};
|
||||||
|
|
||||||
virtual const char* get_name() override;
|
class dynamic_mask_factory : public obs::source_factory<filter::dynamic_mask::dynamic_mask_factory,
|
||||||
|
filter::dynamic_mask::dynamic_mask_instance> {
|
||||||
|
static std::shared_ptr<filter::dynamic_mask::dynamic_mask_factory> factory_instance;
|
||||||
|
|
||||||
virtual void get_defaults2(obs_data_t* data) override;
|
public: // Singleton
|
||||||
|
static void initialize()
|
||||||
|
{
|
||||||
|
factory_instance = std::make_shared<filter::dynamic_mask::dynamic_mask_factory>();
|
||||||
|
}
|
||||||
|
|
||||||
virtual obs_properties_t* get_properties2(filter::dynamic_mask::dynamic_mask_instance* data) override;
|
static void finalize()
|
||||||
|
{
|
||||||
|
factory_instance.reset();
|
||||||
|
}
|
||||||
|
|
||||||
std::string translate_string(const char* format, ...);
|
static std::shared_ptr<dynamic_mask_factory> get()
|
||||||
};
|
{
|
||||||
} // namespace dynamic_mask
|
return factory_instance;
|
||||||
} // namespace filter
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::list<std::string> _translation_cache;
|
||||||
|
|
||||||
|
public:
|
||||||
|
dynamic_mask_factory();
|
||||||
|
virtual ~dynamic_mask_factory() override;
|
||||||
|
|
||||||
|
virtual const char* get_name() override;
|
||||||
|
|
||||||
|
virtual void get_defaults2(obs_data_t* data) override;
|
||||||
|
|
||||||
|
virtual obs_properties_t* get_properties2(filter::dynamic_mask::dynamic_mask_instance* data) override;
|
||||||
|
|
||||||
|
std::string translate_string(const char* format, ...);
|
||||||
|
};
|
||||||
|
} // namespace filter::dynamic_mask
|
||||||
|
|
|
@ -65,10 +65,11 @@
|
||||||
#define ST_SDF_SCALE "Filter.SDFEffects.SDF.Scale"
|
#define ST_SDF_SCALE "Filter.SDFEffects.SDF.Scale"
|
||||||
#define ST_SDF_THRESHOLD "Filter.SDFEffects.SDF.Threshold"
|
#define ST_SDF_THRESHOLD "Filter.SDFEffects.SDF.Threshold"
|
||||||
|
|
||||||
std::shared_ptr<filter::sdf_effects::sdf_effects_factory> filter::sdf_effects::sdf_effects_factory::factory_instance =
|
using namespace filter;
|
||||||
nullptr;
|
|
||||||
|
|
||||||
filter::sdf_effects::sdf_effects_instance::sdf_effects_instance(obs_data_t* settings, obs_source_t* self)
|
std::shared_ptr<sdf_effects::sdf_effects_factory> sdf_effects::sdf_effects_factory::factory_instance = nullptr;
|
||||||
|
|
||||||
|
sdf_effects::sdf_effects_instance::sdf_effects_instance(obs_data_t* settings, obs_source_t* self)
|
||||||
: obs::source_instance(settings, self), _source_rendered(false), _sdf_scale(1.0), _sdf_threshold(),
|
: obs::source_instance(settings, self), _source_rendered(false), _sdf_scale(1.0), _sdf_threshold(),
|
||||||
_output_rendered(false), _inner_shadow(false), _inner_shadow_color(), _inner_shadow_range_min(),
|
_output_rendered(false), _inner_shadow(false), _inner_shadow_color(), _inner_shadow_range_min(),
|
||||||
_inner_shadow_range_max(), _inner_shadow_offset_x(), _inner_shadow_offset_y(), _outer_shadow(false),
|
_inner_shadow_range_max(), _inner_shadow_offset_x(), _inner_shadow_offset_y(), _outer_shadow(false),
|
||||||
|
@ -100,14 +101,14 @@ filter::sdf_effects::sdf_effects_instance::sdf_effects_instance(obs_data_t* sett
|
||||||
for (auto& kv : load_arr) {
|
for (auto& kv : load_arr) {
|
||||||
char* path = obs_module_file(kv.first);
|
char* path = obs_module_file(kv.first);
|
||||||
if (!path) {
|
if (!path) {
|
||||||
P_LOG_ERROR(LOG_PREFIX "Unable to load _effect '%s' as file is missing or locked.", kv.first);
|
LOG_ERROR(LOG_PREFIX "Unable to load _effect '%s' as file is missing or locked.", kv.first);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
kv.second = gs::effect::create(path);
|
kv.second = gs::effect::create(path);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR(LOG_PREFIX "Failed to load _effect '%s' (located at '%s') with error(s): %s", kv.first,
|
LOG_ERROR(LOG_PREFIX "Failed to load _effect '%s' (located at '%s') with error(s): %s", kv.first, path,
|
||||||
path, ex.what());
|
ex.what());
|
||||||
}
|
}
|
||||||
bfree(path);
|
bfree(path);
|
||||||
}
|
}
|
||||||
|
@ -116,9 +117,9 @@ filter::sdf_effects::sdf_effects_instance::sdf_effects_instance(obs_data_t* sett
|
||||||
update(settings);
|
update(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
filter::sdf_effects::sdf_effects_instance::~sdf_effects_instance() {}
|
sdf_effects::sdf_effects_instance::~sdf_effects_instance() {}
|
||||||
|
|
||||||
void filter::sdf_effects::sdf_effects_instance::update(obs_data_t* data)
|
void sdf_effects::sdf_effects_instance::update(obs_data_t* data)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
_outer_shadow =
|
_outer_shadow =
|
||||||
|
@ -253,12 +254,12 @@ void filter::sdf_effects::sdf_effects_instance::update(obs_data_t* data)
|
||||||
_sdf_threshold = float_t(obs_data_get_double(data, ST_SDF_THRESHOLD) / 100.0);
|
_sdf_threshold = float_t(obs_data_get_double(data, ST_SDF_THRESHOLD) / 100.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::sdf_effects::sdf_effects_instance::load(obs_data_t* settings)
|
void sdf_effects::sdf_effects_instance::load(obs_data_t* settings)
|
||||||
{
|
{
|
||||||
update(settings);
|
update(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::sdf_effects::sdf_effects_instance::video_tick(float)
|
void sdf_effects::sdf_effects_instance::video_tick(float)
|
||||||
{
|
{
|
||||||
uint32_t width = 1;
|
uint32_t width = 1;
|
||||||
uint32_t height = 1;
|
uint32_t height = 1;
|
||||||
|
@ -279,7 +280,7 @@ void filter::sdf_effects::sdf_effects_instance::video_tick(float)
|
||||||
_output_rendered = false;
|
_output_rendered = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect)
|
void sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect)
|
||||||
{
|
{
|
||||||
obs_source_t* parent = obs_filter_get_parent(_self);
|
obs_source_t* parent = obs_filter_get_parent(_self);
|
||||||
obs_source_t* target = obs_filter_get_target(_self);
|
obs_source_t* target = obs_filter_get_target(_self);
|
||||||
|
@ -508,7 +509,7 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
filter::sdf_effects::sdf_effects_factory::sdf_effects_factory()
|
sdf_effects::sdf_effects_factory::sdf_effects_factory()
|
||||||
{
|
{
|
||||||
_info.id = "obs-stream-effects-filter-sdf-effects";
|
_info.id = "obs-stream-effects-filter-sdf-effects";
|
||||||
_info.type = OBS_SOURCE_TYPE_FILTER;
|
_info.type = OBS_SOURCE_TYPE_FILTER;
|
||||||
|
@ -518,14 +519,14 @@ filter::sdf_effects::sdf_effects_factory::sdf_effects_factory()
|
||||||
finish_setup();
|
finish_setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
filter::sdf_effects::sdf_effects_factory::~sdf_effects_factory() {}
|
sdf_effects::sdf_effects_factory::~sdf_effects_factory() {}
|
||||||
|
|
||||||
const char* filter::sdf_effects::sdf_effects_factory::get_name()
|
const char* sdf_effects::sdf_effects_factory::get_name()
|
||||||
{
|
{
|
||||||
return D_TRANSLATE(ST);
|
return D_TRANSLATE(ST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::sdf_effects::sdf_effects_factory::get_defaults2(obs_data_t* data)
|
void sdf_effects::sdf_effects_factory::get_defaults2(obs_data_t* data)
|
||||||
{
|
{
|
||||||
obs_data_set_default_bool(data, ST_SHADOW_OUTER, false);
|
obs_data_set_default_bool(data, ST_SHADOW_OUTER, false);
|
||||||
obs_data_set_default_int(data, ST_SHADOW_OUTER_COLOR, 0x00000000);
|
obs_data_set_default_int(data, ST_SHADOW_OUTER_COLOR, 0x00000000);
|
||||||
|
@ -578,9 +579,9 @@ try {
|
||||||
obs_property_set_visible(obs_properties_get(props, ST_SHADOW_INNER_ALPHA), v);
|
obs_property_set_visible(obs_properties_get(props, ST_SHADOW_INNER_ALPHA), v);
|
||||||
return true;
|
return true;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cb_modified_shadow_outside(void*, obs_properties_t* props, obs_property*, obs_data_t* settings) noexcept
|
bool cb_modified_shadow_outside(void*, obs_properties_t* props, obs_property*, obs_data_t* settings) noexcept
|
||||||
|
@ -594,9 +595,9 @@ try {
|
||||||
obs_property_set_visible(obs_properties_get(props, ST_SHADOW_OUTER_ALPHA), v);
|
obs_property_set_visible(obs_properties_get(props, ST_SHADOW_OUTER_ALPHA), v);
|
||||||
return true;
|
return true;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cb_modified_glow_inside(void*, obs_properties_t* props, obs_property*, obs_data_t* settings) noexcept
|
bool cb_modified_glow_inside(void*, obs_properties_t* props, obs_property*, obs_data_t* settings) noexcept
|
||||||
|
@ -608,9 +609,9 @@ try {
|
||||||
obs_property_set_visible(obs_properties_get(props, ST_GLOW_INNER_SHARPNESS), v);
|
obs_property_set_visible(obs_properties_get(props, ST_GLOW_INNER_SHARPNESS), v);
|
||||||
return true;
|
return true;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cb_modified_glow_outside(void*, obs_properties_t* props, obs_property*, obs_data_t* settings) noexcept
|
bool cb_modified_glow_outside(void*, obs_properties_t* props, obs_property*, obs_data_t* settings) noexcept
|
||||||
|
@ -622,9 +623,9 @@ try {
|
||||||
obs_property_set_visible(obs_properties_get(props, ST_GLOW_OUTER_SHARPNESS), v);
|
obs_property_set_visible(obs_properties_get(props, ST_GLOW_OUTER_SHARPNESS), v);
|
||||||
return true;
|
return true;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cb_modified_outline(void*, obs_properties_t* props, obs_property*, obs_data_t* settings) noexcept
|
bool cb_modified_outline(void*, obs_properties_t* props, obs_property*, obs_data_t* settings) noexcept
|
||||||
|
@ -637,9 +638,9 @@ try {
|
||||||
obs_property_set_visible(obs_properties_get(props, ST_OUTLINE_SHARPNESS), v);
|
obs_property_set_visible(obs_properties_get(props, ST_OUTLINE_SHARPNESS), v);
|
||||||
return true;
|
return true;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cb_modified_advanced(void*, obs_properties_t* props, obs_property*, obs_data_t* settings) noexcept
|
bool cb_modified_advanced(void*, obs_properties_t* props, obs_property*, obs_data_t* settings) noexcept
|
||||||
|
@ -649,13 +650,12 @@ try {
|
||||||
obs_property_set_visible(obs_properties_get(props, ST_SDF_THRESHOLD), show_advanced);
|
obs_property_set_visible(obs_properties_get(props, ST_SDF_THRESHOLD), show_advanced);
|
||||||
return true;
|
return true;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_properties_t*
|
obs_properties_t* sdf_effects::sdf_effects_factory::get_properties2(sdf_effects::sdf_effects_instance* data)
|
||||||
filter::sdf_effects::sdf_effects_factory::get_properties2(filter::sdf_effects::sdf_effects_instance* data)
|
|
||||||
{
|
{
|
||||||
obs_properties_t* props = obs_properties_create();
|
obs_properties_t* props = obs_properties_create();
|
||||||
obs_property_t* p = nullptr;
|
obs_property_t* p = nullptr;
|
||||||
|
|
|
@ -37,103 +37,101 @@
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace filter {
|
namespace filter::sdf_effects {
|
||||||
namespace sdf_effects {
|
class sdf_effects_instance : public obs::source_instance {
|
||||||
class sdf_effects_instance : public obs::source_instance {
|
gs::effect _sdf_producer_effect;
|
||||||
gs::effect _sdf_producer_effect;
|
gs::effect _sdf_consumer_effect;
|
||||||
gs::effect _sdf_consumer_effect;
|
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
std::shared_ptr<gs::rendertarget> _source_rt;
|
std::shared_ptr<gs::rendertarget> _source_rt;
|
||||||
std::shared_ptr<gs::texture> _source_texture;
|
std::shared_ptr<gs::texture> _source_texture;
|
||||||
bool _source_rendered;
|
bool _source_rendered;
|
||||||
|
|
||||||
// Distance Field
|
// Distance Field
|
||||||
std::shared_ptr<gs::rendertarget> _sdf_write;
|
std::shared_ptr<gs::rendertarget> _sdf_write;
|
||||||
std::shared_ptr<gs::rendertarget> _sdf_read;
|
std::shared_ptr<gs::rendertarget> _sdf_read;
|
||||||
std::shared_ptr<gs::texture> _sdf_texture;
|
std::shared_ptr<gs::texture> _sdf_texture;
|
||||||
double_t _sdf_scale;
|
double_t _sdf_scale;
|
||||||
float_t _sdf_threshold;
|
float_t _sdf_threshold;
|
||||||
|
|
||||||
// Effects
|
// Effects
|
||||||
bool _output_rendered;
|
bool _output_rendered;
|
||||||
std::shared_ptr<gs::texture> _output_texture;
|
std::shared_ptr<gs::texture> _output_texture;
|
||||||
std::shared_ptr<gs::rendertarget> _output_rt;
|
std::shared_ptr<gs::rendertarget> _output_rt;
|
||||||
/// Inner Shadow
|
/// Inner Shadow
|
||||||
bool _inner_shadow;
|
bool _inner_shadow;
|
||||||
vec4 _inner_shadow_color;
|
vec4 _inner_shadow_color;
|
||||||
float_t _inner_shadow_range_min;
|
float_t _inner_shadow_range_min;
|
||||||
float_t _inner_shadow_range_max;
|
float_t _inner_shadow_range_max;
|
||||||
float_t _inner_shadow_offset_x;
|
float_t _inner_shadow_offset_x;
|
||||||
float_t _inner_shadow_offset_y;
|
float_t _inner_shadow_offset_y;
|
||||||
/// Outer Shadow
|
/// Outer Shadow
|
||||||
bool _outer_shadow;
|
bool _outer_shadow;
|
||||||
vec4 _outer_shadow_color;
|
vec4 _outer_shadow_color;
|
||||||
float_t _outer_shadow_range_min;
|
float_t _outer_shadow_range_min;
|
||||||
float_t _outer_shadow_range_max;
|
float_t _outer_shadow_range_max;
|
||||||
float_t _outer_shadow_offset_x;
|
float_t _outer_shadow_offset_x;
|
||||||
float_t _outer_shadow_offset_y;
|
float_t _outer_shadow_offset_y;
|
||||||
/// Inner Glow
|
/// Inner Glow
|
||||||
bool _inner_glow;
|
bool _inner_glow;
|
||||||
vec4 _inner_glow_color;
|
vec4 _inner_glow_color;
|
||||||
float_t _inner_glow_width;
|
float_t _inner_glow_width;
|
||||||
float_t _inner_glow_sharpness;
|
float_t _inner_glow_sharpness;
|
||||||
float_t _inner_glow_sharpness_inv;
|
float_t _inner_glow_sharpness_inv;
|
||||||
/// Outer Glow
|
/// Outer Glow
|
||||||
bool _outer_glow;
|
bool _outer_glow;
|
||||||
vec4 _outer_glow_color;
|
vec4 _outer_glow_color;
|
||||||
float_t _outer_glow_width;
|
float_t _outer_glow_width;
|
||||||
float_t _outer_glow_sharpness;
|
float_t _outer_glow_sharpness;
|
||||||
float_t _outer_glow_sharpness_inv;
|
float_t _outer_glow_sharpness_inv;
|
||||||
/// Outline
|
/// Outline
|
||||||
bool _outline;
|
bool _outline;
|
||||||
vec4 _outline_color;
|
vec4 _outline_color;
|
||||||
float_t _outline_width;
|
float_t _outline_width;
|
||||||
float_t _outline_offset;
|
float_t _outline_offset;
|
||||||
float_t _outline_sharpness;
|
float_t _outline_sharpness;
|
||||||
float_t _outline_sharpness_inv;
|
float_t _outline_sharpness_inv;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
sdf_effects_instance(obs_data_t* settings, obs_source_t* self);
|
sdf_effects_instance(obs_data_t* settings, obs_source_t* self);
|
||||||
virtual ~sdf_effects_instance();
|
virtual ~sdf_effects_instance();
|
||||||
|
|
||||||
virtual void update(obs_data_t* settings) override;
|
virtual void update(obs_data_t* settings) override;
|
||||||
virtual void load(obs_data_t* settings) override;
|
virtual void load(obs_data_t* settings) override;
|
||||||
|
|
||||||
virtual void video_tick(float) override;
|
virtual void video_tick(float) override;
|
||||||
virtual void video_render(gs_effect_t*) override;
|
virtual void video_render(gs_effect_t*) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class sdf_effects_factory : public obs::source_factory<filter::sdf_effects::sdf_effects_factory,
|
class sdf_effects_factory : public obs::source_factory<filter::sdf_effects::sdf_effects_factory,
|
||||||
filter::sdf_effects::sdf_effects_instance> {
|
filter::sdf_effects::sdf_effects_instance> {
|
||||||
static std::shared_ptr<filter::sdf_effects::sdf_effects_factory> factory_instance;
|
static std::shared_ptr<filter::sdf_effects::sdf_effects_factory> factory_instance;
|
||||||
|
|
||||||
public: // Singleton
|
public: // Singleton
|
||||||
static void initialize()
|
static void initialize()
|
||||||
{
|
{
|
||||||
factory_instance = std::make_shared<filter::sdf_effects::sdf_effects_factory>();
|
factory_instance = std::make_shared<filter::sdf_effects::sdf_effects_factory>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void finalize()
|
static void finalize()
|
||||||
{
|
{
|
||||||
factory_instance.reset();
|
factory_instance.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::shared_ptr<sdf_effects_factory> get()
|
static std::shared_ptr<sdf_effects_factory> get()
|
||||||
{
|
{
|
||||||
return factory_instance;
|
return factory_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
sdf_effects_factory();
|
sdf_effects_factory();
|
||||||
virtual ~sdf_effects_factory();
|
virtual ~sdf_effects_factory();
|
||||||
|
|
||||||
virtual const char* get_name() override;
|
virtual const char* get_name() override;
|
||||||
|
|
||||||
virtual void get_defaults2(obs_data_t* data) override;
|
virtual void get_defaults2(obs_data_t* data) override;
|
||||||
|
|
||||||
virtual obs_properties_t* get_properties2(filter::sdf_effects::sdf_effects_instance* data) override;
|
virtual obs_properties_t* get_properties2(filter::sdf_effects::sdf_effects_instance* data) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sdf_effects
|
} // namespace filter::sdf_effects
|
||||||
} // namespace filter
|
|
||||||
|
|
|
@ -64,6 +64,8 @@
|
||||||
#define ST_ROTATION_ORDER_ZYX "Filter.Transform.Rotation.Order.ZYX"
|
#define ST_ROTATION_ORDER_ZYX "Filter.Transform.Rotation.Order.ZYX"
|
||||||
#define ST_MIPMAPPING "Filter.Transform.Mipmapping"
|
#define ST_MIPMAPPING "Filter.Transform.Mipmapping"
|
||||||
|
|
||||||
|
using namespace filter;
|
||||||
|
|
||||||
static const float farZ = 2097152.0f; // 2 pow 21
|
static const float farZ = 2097152.0f; // 2 pow 21
|
||||||
static const float nearZ = 1.0f / farZ;
|
static const float nearZ = 1.0f / farZ;
|
||||||
|
|
||||||
|
@ -78,7 +80,7 @@ enum RotationOrder : int64_t {
|
||||||
ZYX,
|
ZYX,
|
||||||
};
|
};
|
||||||
|
|
||||||
filter::transform::transform_instance::transform_instance(obs_data_t* data, obs_source_t* context)
|
transform::transform_instance::transform_instance(obs_data_t* data, obs_source_t* context)
|
||||||
: obs::source_instance(data, context), _cache_rendered(), _mipmap_enabled(), _mipmap_strength(),
|
: obs::source_instance(data, context), _cache_rendered(), _mipmap_enabled(), _mipmap_strength(),
|
||||||
_mipmap_generator(), _source_rendered(), _source_size(), _update_mesh(), _rotation_order(),
|
_mipmap_generator(), _source_rendered(), _source_size(), _update_mesh(), _rotation_order(),
|
||||||
_camera_orthographic(), _camera_fov()
|
_camera_orthographic(), _camera_fov()
|
||||||
|
@ -99,7 +101,7 @@ filter::transform::transform_instance::transform_instance(obs_data_t* data, obs_
|
||||||
update(data);
|
update(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
filter::transform::transform_instance::~transform_instance()
|
transform::transform_instance::~transform_instance()
|
||||||
{
|
{
|
||||||
_shear.reset();
|
_shear.reset();
|
||||||
_scale.reset();
|
_scale.reset();
|
||||||
|
@ -111,12 +113,12 @@ filter::transform::transform_instance::~transform_instance()
|
||||||
_mipmap_texture.reset();
|
_mipmap_texture.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::transform::transform_instance::load(obs_data_t* settings)
|
void transform::transform_instance::load(obs_data_t* settings)
|
||||||
{
|
{
|
||||||
update(settings);
|
update(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::transform::transform_instance::update(obs_data_t* settings)
|
void transform::transform_instance::update(obs_data_t* settings)
|
||||||
{
|
{
|
||||||
// Camera
|
// Camera
|
||||||
_camera_orthographic = obs_data_get_int(settings, ST_CAMERA) == 0;
|
_camera_orthographic = obs_data_get_int(settings, ST_CAMERA) == 0;
|
||||||
|
@ -145,7 +147,7 @@ void filter::transform::transform_instance::update(obs_data_t* settings)
|
||||||
_update_mesh = true;
|
_update_mesh = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::transform::transform_instance::video_tick(float)
|
void transform::transform_instance::video_tick(float)
|
||||||
{
|
{
|
||||||
uint32_t width = 0;
|
uint32_t width = 0;
|
||||||
uint32_t height = 0;
|
uint32_t height = 0;
|
||||||
|
@ -263,7 +265,7 @@ void filter::transform::transform_instance::video_tick(float)
|
||||||
_source_rendered = false;
|
_source_rendered = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::transform::transform_instance::video_render(gs_effect_t*)
|
void transform::transform_instance::video_render(gs_effect_t*)
|
||||||
{
|
{
|
||||||
obs_source_t* parent = obs_filter_get_parent(_self);
|
obs_source_t* parent = obs_filter_get_parent(_self);
|
||||||
obs_source_t* target = obs_filter_get_target(_self);
|
obs_source_t* target = obs_filter_get_target(_self);
|
||||||
|
@ -397,9 +399,9 @@ void filter::transform::transform_instance::video_render(gs_effect_t*)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<filter::transform::transform_factory> filter::transform::transform_factory::factory_instance = nullptr;
|
std::shared_ptr<transform::transform_factory> transform::transform_factory::factory_instance = nullptr;
|
||||||
|
|
||||||
filter::transform::transform_factory::transform_factory()
|
transform::transform_factory::transform_factory()
|
||||||
{
|
{
|
||||||
_info.id = "obs-stream-effects-filter-transform";
|
_info.id = "obs-stream-effects-filter-transform";
|
||||||
_info.type = OBS_SOURCE_TYPE_FILTER;
|
_info.type = OBS_SOURCE_TYPE_FILTER;
|
||||||
|
@ -409,14 +411,14 @@ filter::transform::transform_factory::transform_factory()
|
||||||
finish_setup();
|
finish_setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
filter::transform::transform_factory::~transform_factory() {}
|
transform::transform_factory::~transform_factory() {}
|
||||||
|
|
||||||
const char* filter::transform::transform_factory::get_name()
|
const char* transform::transform_factory::get_name()
|
||||||
{
|
{
|
||||||
return D_TRANSLATE(ST);
|
return D_TRANSLATE(ST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::transform::transform_factory::get_defaults2(obs_data_t* settings)
|
void transform::transform_factory::get_defaults2(obs_data_t* settings)
|
||||||
{
|
{
|
||||||
obs_data_set_default_int(settings, ST_CAMERA, (int64_t)CameraMode::Orthographic);
|
obs_data_set_default_int(settings, ST_CAMERA, (int64_t)CameraMode::Orthographic);
|
||||||
obs_data_set_default_double(settings, ST_CAMERA_FIELDOFVIEW, 90.0);
|
obs_data_set_default_double(settings, ST_CAMERA_FIELDOFVIEW, 90.0);
|
||||||
|
@ -456,12 +458,12 @@ try {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_properties_t* filter::transform::transform_factory::get_properties2(filter::transform::transform_instance* data)
|
obs_properties_t* transform::transform_factory::get_properties2(transform::transform_instance* data)
|
||||||
{
|
{
|
||||||
obs_properties_t* pr = obs_properties_create();
|
obs_properties_t* pr = obs_properties_create();
|
||||||
|
|
||||||
|
|
|
@ -27,81 +27,79 @@
|
||||||
#include "obs/obs-source-factory.hpp"
|
#include "obs/obs-source-factory.hpp"
|
||||||
#include "plugin.hpp"
|
#include "plugin.hpp"
|
||||||
|
|
||||||
namespace filter {
|
namespace filter::transform {
|
||||||
namespace transform {
|
class transform_instance : public obs::source_instance {
|
||||||
class transform_instance : public obs::source_instance {
|
// Cache
|
||||||
// Cache
|
bool _cache_rendered;
|
||||||
bool _cache_rendered;
|
std::shared_ptr<gs::rendertarget> _cache_rt;
|
||||||
std::shared_ptr<gs::rendertarget> _cache_rt;
|
std::shared_ptr<gs::texture> _cache_texture;
|
||||||
std::shared_ptr<gs::texture> _cache_texture;
|
|
||||||
|
|
||||||
// Mip-mapping
|
// Mip-mapping
|
||||||
bool _mipmap_enabled;
|
bool _mipmap_enabled;
|
||||||
bool _mipmap_rendered;
|
bool _mipmap_rendered;
|
||||||
double_t _mipmap_strength;
|
double_t _mipmap_strength;
|
||||||
gs::mipmapper::generator _mipmap_generator;
|
gs::mipmapper::generator _mipmap_generator;
|
||||||
gs::mipmapper _mipmapper;
|
gs::mipmapper _mipmapper;
|
||||||
std::shared_ptr<gs::texture> _mipmap_texture;
|
std::shared_ptr<gs::texture> _mipmap_texture;
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
bool _source_rendered;
|
bool _source_rendered;
|
||||||
std::pair<uint32_t, uint32_t> _source_size;
|
std::pair<uint32_t, uint32_t> _source_size;
|
||||||
std::shared_ptr<gs::rendertarget> _source_rt;
|
std::shared_ptr<gs::rendertarget> _source_rt;
|
||||||
std::shared_ptr<gs::texture> _source_texture;
|
std::shared_ptr<gs::texture> _source_texture;
|
||||||
|
|
||||||
// Mesh
|
// Mesh
|
||||||
bool _update_mesh;
|
bool _update_mesh;
|
||||||
std::shared_ptr<gs::vertex_buffer> _vertex_buffer;
|
std::shared_ptr<gs::vertex_buffer> _vertex_buffer;
|
||||||
uint32_t _rotation_order;
|
uint32_t _rotation_order;
|
||||||
std::unique_ptr<util::vec3a> _position;
|
std::unique_ptr<util::vec3a> _position;
|
||||||
std::unique_ptr<util::vec3a> _rotation;
|
std::unique_ptr<util::vec3a> _rotation;
|
||||||
std::unique_ptr<util::vec3a> _scale;
|
std::unique_ptr<util::vec3a> _scale;
|
||||||
std::unique_ptr<util::vec3a> _shear;
|
std::unique_ptr<util::vec3a> _shear;
|
||||||
|
|
||||||
// Camera
|
// Camera
|
||||||
bool _camera_orthographic;
|
bool _camera_orthographic;
|
||||||
float_t _camera_fov;
|
float_t _camera_fov;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
transform_instance(obs_data_t*, obs_source_t*);
|
transform_instance(obs_data_t*, obs_source_t*);
|
||||||
virtual ~transform_instance() override;
|
virtual ~transform_instance() override;
|
||||||
|
|
||||||
virtual void load(obs_data_t* settings) override;
|
virtual void load(obs_data_t* settings) override;
|
||||||
virtual void update(obs_data_t*) override;
|
virtual void update(obs_data_t*) override;
|
||||||
|
|
||||||
virtual void video_tick(float) override;
|
virtual void video_tick(float) override;
|
||||||
virtual void video_render(gs_effect_t*) override;
|
virtual void video_render(gs_effect_t*) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class transform_factory
|
class transform_factory
|
||||||
: public obs::source_factory<filter::transform::transform_factory, filter::transform::transform_instance> {
|
: public obs::source_factory<filter::transform::transform_factory, filter::transform::transform_instance> {
|
||||||
static std::shared_ptr<filter::transform::transform_factory> factory_instance;
|
static std::shared_ptr<filter::transform::transform_factory> factory_instance;
|
||||||
|
|
||||||
public: // Singleton
|
public: // Singleton
|
||||||
static void initialize()
|
static void initialize()
|
||||||
{
|
{
|
||||||
factory_instance = std::make_shared<filter::transform::transform_factory>();
|
factory_instance = std::make_shared<filter::transform::transform_factory>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void finalize()
|
static void finalize()
|
||||||
{
|
{
|
||||||
factory_instance.reset();
|
factory_instance.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::shared_ptr<transform_factory> get()
|
static std::shared_ptr<transform_factory> get()
|
||||||
{
|
{
|
||||||
return factory_instance;
|
return factory_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
transform_factory();
|
transform_factory();
|
||||||
virtual ~transform_factory() override;
|
virtual ~transform_factory() override;
|
||||||
|
|
||||||
virtual const char* get_name() override;
|
virtual const char* get_name() override;
|
||||||
|
|
||||||
virtual void get_defaults2(obs_data_t* data) override;
|
virtual void get_defaults2(obs_data_t* data) override;
|
||||||
|
|
||||||
virtual obs_properties_t* get_properties2(filter::transform::transform_instance* data) override;
|
virtual obs_properties_t* get_properties2(filter::transform::transform_instance* data) override;
|
||||||
};
|
};
|
||||||
} // namespace transform
|
} // namespace filter::transform
|
||||||
} // namespace filter
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ gfx::blur::box_linear_data::box_linear_data()
|
||||||
_effect = gs::effect::create(file);
|
_effect = gs::effect::create(file);
|
||||||
bfree(file);
|
bfree(file);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("<gfx::blur::box_linear> Failed to load _effect.");
|
LOG_ERROR("<gfx::blur::box_linear> Failed to load _effect.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ gfx::blur::box_data::box_data()
|
||||||
_effect = gs::effect::create(file);
|
_effect = gs::effect::create(file);
|
||||||
bfree(file);
|
bfree(file);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("<gfx::blur::box> Failed to load _effect.");
|
LOG_ERROR("<gfx::blur::box> Failed to load _effect.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ gfx::blur::dual_filtering_data::dual_filtering_data()
|
||||||
_effect = gs::effect::create(file);
|
_effect = gs::effect::create(file);
|
||||||
bfree(file);
|
bfree(file);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("<gfx::blur::box_linear> Failed to load _effect.");
|
LOG_ERROR("<gfx::blur::box_linear> Failed to load _effect.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,12 +131,12 @@ gfx::shader::basic_parameter::basic_parameter(gs::effect_parameter param, std::s
|
||||||
load_parameter_data(annoev, entry.data);
|
load_parameter_data(annoev, entry.data);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
P_LOG_WARNING("[%s] Parameter enumeration entry '%s' is of invalid type, must be string.",
|
LOG_WARNING("[%s] Parameter enumeration entry '%s' is of invalid type, must be string.",
|
||||||
get_name().c_str(), string_buffer);
|
get_name().c_str(), string_buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
P_LOG_WARNING("[%s] Enumeration is missing entries.", get_name().c_str());
|
LOG_WARNING("[%s] Enumeration is missing entries.", get_name().c_str());
|
||||||
_field_type = basic_field_type::Input;
|
_field_type = basic_field_type::Input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ try {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Loading shader '%s' failed with error: %s", file.c_str(), ex.what());
|
LOG_ERROR("Loading shader '%s' failed with error: %s", file.c_str(), ex.what());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ try {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Loading shader '%s' failed with error: %s", file.c_str(), ex.what());
|
LOG_ERROR("Loading shader '%s' failed with error: %s", file.c_str(), ex.what());
|
||||||
return false;
|
return false;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -262,7 +262,7 @@ void gs::mipmapper::rebuild(std::shared_ptr<gs::texture> source, std::shared_ptr
|
||||||
gs_draw(gs_draw_mode::GS_TRIS, 0, _vb->size());
|
gs_draw(gs_draw_mode::GS_TRIS, 0, _vb->size());
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Failed to render mipmap layer.");
|
LOG_ERROR("Failed to render mipmap layer.");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(WIN32) || defined(WIN64)
|
#if defined(WIN32) || defined(WIN64)
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "gs-sampler.hpp"
|
#include "gs-sampler.hpp"
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
gs::sampler::sampler()
|
gs::sampler::sampler()
|
||||||
{
|
{
|
||||||
|
@ -97,7 +98,8 @@ void gs::sampler::set_border_color(uint32_t v)
|
||||||
void gs::sampler::set_border_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
void gs::sampler::set_border_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
{
|
{
|
||||||
_dirty = true;
|
_dirty = true;
|
||||||
_sampler_info.border_color = a << 24 | r << 16 | g << 8 | b;
|
_sampler_info.border_color = (static_cast<uint32_t>(a) << 24) | (static_cast<uint32_t>(r) << 16)
|
||||||
|
| (static_cast<uint32_t>(g) << 8) | static_cast<uint32_t>(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t gs::sampler::get_border_color()
|
uint32_t gs::sampler::get_border_color()
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef STREAMEFFECTS_SOURCE_FACTORY_HPP
|
#ifndef STREAMFX_SOURCE_FACTORY_HPP
|
||||||
#define STREAMEFFECTS_SOURCE_FACTORY_HPP
|
#define STREAMFX_SOURCE_FACTORY_HPP
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
@ -183,10 +183,10 @@ namespace obs {
|
||||||
return reinterpret_cast<_factory*>(type_data)->get_name();
|
return reinterpret_cast<_factory*>(type_data)->get_name();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,10 +194,10 @@ namespace obs {
|
||||||
try {
|
try {
|
||||||
return reinterpret_cast<_factory*>(obs_source_get_type_data(source))->create(settings, source);
|
return reinterpret_cast<_factory*>(obs_source_get_type_data(source))->create(settings, source);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,9 +206,9 @@ namespace obs {
|
||||||
if (type_data)
|
if (type_data)
|
||||||
reinterpret_cast<_factory*>(type_data)->get_defaults2(settings);
|
reinterpret_cast<_factory*>(type_data)->get_defaults2(settings);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static obs_properties_t* _get_properties2(void* data, void* type_data) noexcept
|
static obs_properties_t* _get_properties2(void* data, void* type_data) noexcept
|
||||||
|
@ -217,10 +217,10 @@ namespace obs {
|
||||||
return reinterpret_cast<_factory*>(type_data)->get_properties2(reinterpret_cast<_instance*>(data));
|
return reinterpret_cast<_factory*>(type_data)->get_properties2(reinterpret_cast<_instance*>(data));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,9 +230,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
delete reinterpret_cast<_instance*>(data);
|
delete reinterpret_cast<_instance*>(data);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t _get_width(void* data) noexcept
|
static uint32_t _get_width(void* data) noexcept
|
||||||
|
@ -241,10 +241,10 @@ namespace obs {
|
||||||
return reinterpret_cast<_instance*>(data)->get_width();
|
return reinterpret_cast<_instance*>(data)->get_width();
|
||||||
return 0;
|
return 0;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
return 0;
|
return 0;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,10 +254,10 @@ namespace obs {
|
||||||
return reinterpret_cast<_instance*>(data)->get_height();
|
return reinterpret_cast<_instance*>(data)->get_height();
|
||||||
return 0;
|
return 0;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
return 0;
|
return 0;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,9 +266,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->update(settings);
|
reinterpret_cast<_instance*>(data)->update(settings);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _activate(void* data) noexcept
|
static void _activate(void* data) noexcept
|
||||||
|
@ -276,9 +276,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->activate();
|
reinterpret_cast<_instance*>(data)->activate();
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _deactivate(void* data) noexcept
|
static void _deactivate(void* data) noexcept
|
||||||
|
@ -286,9 +286,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->deactivate();
|
reinterpret_cast<_instance*>(data)->deactivate();
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _show(void* data) noexcept
|
static void _show(void* data) noexcept
|
||||||
|
@ -296,9 +296,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->show();
|
reinterpret_cast<_instance*>(data)->show();
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _hide(void* data) noexcept
|
static void _hide(void* data) noexcept
|
||||||
|
@ -306,9 +306,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->hide();
|
reinterpret_cast<_instance*>(data)->hide();
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _video_tick(void* data, float seconds) noexcept
|
static void _video_tick(void* data, float seconds) noexcept
|
||||||
|
@ -316,9 +316,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->video_tick(seconds);
|
reinterpret_cast<_instance*>(data)->video_tick(seconds);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _video_render(void* data, gs_effect_t* effect) noexcept
|
static void _video_render(void* data, gs_effect_t* effect) noexcept
|
||||||
|
@ -326,9 +326,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->video_render(effect);
|
reinterpret_cast<_instance*>(data)->video_render(effect);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct obs_source_frame* _filter_video(void* data, struct obs_source_frame* frame) noexcept
|
static struct obs_source_frame* _filter_video(void* data, struct obs_source_frame* frame) noexcept
|
||||||
|
@ -337,10 +337,10 @@ namespace obs {
|
||||||
return reinterpret_cast<_instance*>(data)->filter_video(frame);
|
return reinterpret_cast<_instance*>(data)->filter_video(frame);
|
||||||
return frame;
|
return frame;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
return frame;
|
return frame;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,10 +350,10 @@ namespace obs {
|
||||||
return reinterpret_cast<_instance*>(data)->filter_audio(frame);
|
return reinterpret_cast<_instance*>(data)->filter_audio(frame);
|
||||||
return frame;
|
return frame;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
return frame;
|
return frame;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,9 +362,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->enum_active_sources(enum_callback, param);
|
reinterpret_cast<_instance*>(data)->enum_active_sources(enum_callback, param);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _save(void* data, obs_data_t* settings) noexcept
|
static void _save(void* data, obs_data_t* settings) noexcept
|
||||||
|
@ -372,9 +372,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->save(settings);
|
reinterpret_cast<_instance*>(data)->save(settings);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _load(void* data, obs_data_t* settings) noexcept
|
static void _load(void* data, obs_data_t* settings) noexcept
|
||||||
|
@ -382,9 +382,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->load(settings);
|
reinterpret_cast<_instance*>(data)->load(settings);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _mouse_click(void* data, const struct obs_mouse_event* event, int32_t type, bool mouse_up,
|
static void _mouse_click(void* data, const struct obs_mouse_event* event, int32_t type, bool mouse_up,
|
||||||
|
@ -393,9 +393,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->mouse_click(event, type, mouse_up, click_count);
|
reinterpret_cast<_instance*>(data)->mouse_click(event, type, mouse_up, click_count);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _mouse_move(void* data, const struct obs_mouse_event* event, bool mouse_leave) noexcept
|
static void _mouse_move(void* data, const struct obs_mouse_event* event, bool mouse_leave) noexcept
|
||||||
|
@ -403,9 +403,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->mouse_move(event, mouse_leave);
|
reinterpret_cast<_instance*>(data)->mouse_move(event, mouse_leave);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _mouse_wheel(void* data, const struct obs_mouse_event* event, int x_delta, int y_delta) noexcept
|
static void _mouse_wheel(void* data, const struct obs_mouse_event* event, int x_delta, int y_delta) noexcept
|
||||||
|
@ -413,9 +413,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->mouse_wheel(event, x_delta, y_delta);
|
reinterpret_cast<_instance*>(data)->mouse_wheel(event, x_delta, y_delta);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _focus(void* data, bool focus) noexcept
|
static void _focus(void* data, bool focus) noexcept
|
||||||
|
@ -423,9 +423,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->focus(focus);
|
reinterpret_cast<_instance*>(data)->focus(focus);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _key_click(void* data, const struct obs_key_event* event, bool key_up) noexcept
|
static void _key_click(void* data, const struct obs_key_event* event, bool key_up) noexcept
|
||||||
|
@ -433,9 +433,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->key_click(event, key_up);
|
reinterpret_cast<_instance*>(data)->key_click(event, key_up);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _filter_remove(void* data, obs_source_t* source) noexcept
|
static void _filter_remove(void* data, obs_source_t* source) noexcept
|
||||||
|
@ -443,9 +443,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->filter_remove(source);
|
reinterpret_cast<_instance*>(data)->filter_remove(source);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _audio_render(void* data, uint64_t* ts_out, struct obs_source_audio_mix* audio_output,
|
static bool _audio_render(void* data, uint64_t* ts_out, struct obs_source_audio_mix* audio_output,
|
||||||
|
@ -456,10 +456,10 @@ namespace obs {
|
||||||
sample_rate);
|
sample_rate);
|
||||||
return false;
|
return false;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
return false;
|
return false;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,9 +468,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->enum_all_sources(enum_callback, param);
|
reinterpret_cast<_instance*>(data)->enum_all_sources(enum_callback, param);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _transition_start(void* data) noexcept
|
static void _transition_start(void* data) noexcept
|
||||||
|
@ -478,9 +478,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->transition_start();
|
reinterpret_cast<_instance*>(data)->transition_start();
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _transition_stop(void* data) noexcept
|
static void _transition_stop(void* data) noexcept
|
||||||
|
@ -488,9 +488,9 @@ namespace obs {
|
||||||
if (data)
|
if (data)
|
||||||
reinterpret_cast<_instance*>(data)->transition_stop();
|
reinterpret_cast<_instance*>(data)->transition_stop();
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _audio_mix(void* data, uint64_t* ts_out, struct audio_output_data* audio_output, size_t channels,
|
static bool _audio_mix(void* data, uint64_t* ts_out, struct audio_output_data* audio_output, size_t channels,
|
||||||
|
@ -500,10 +500,10 @@ namespace obs {
|
||||||
return reinterpret_cast<_instance*>(data)->audio_mix(ts_out, audio_output, channels, sample_rate);
|
return reinterpret_cast<_instance*>(data)->audio_mix(ts_out, audio_output, channels, sample_rate);
|
||||||
return false;
|
return false;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
return false;
|
return false;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ try {
|
||||||
|
|
||||||
self->_source_map.insert({std::string(name), weak});
|
self->_source_map.insert({std::string(name), weak});
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::source_tracker::source_destroy_handler(void* ptr, calldata_t* data) noexcept
|
void obs::source_tracker::source_destroy_handler(void* ptr, calldata_t* data) noexcept
|
||||||
|
@ -75,7 +75,7 @@ try {
|
||||||
obs_weak_source_release(found->second);
|
obs_weak_source_release(found->second);
|
||||||
self->_source_map.erase(found);
|
self->_source_map.erase(found);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::source_tracker::source_rename_handler(void* ptr, calldata_t* data) noexcept
|
void obs::source_tracker::source_rename_handler(void* ptr, calldata_t* data) noexcept
|
||||||
|
@ -109,7 +109,7 @@ try {
|
||||||
self->_source_map.insert({new_name, found->second});
|
self->_source_map.insert({new_name, found->second});
|
||||||
self->_source_map.erase(found);
|
self->_source_map.erase(found);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::source_tracker::initialize()
|
void obs::source_tracker::initialize()
|
||||||
|
|
|
@ -39,9 +39,9 @@ try {
|
||||||
}
|
}
|
||||||
self->events.destroy(self);
|
self->events.destroy(self);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_remove(void* p, calldata_t*) noexcept
|
void obs::deprecated_source::handle_remove(void* p, calldata_t*) noexcept
|
||||||
|
@ -52,9 +52,9 @@ try {
|
||||||
}
|
}
|
||||||
self->events.remove(self);
|
self->events.remove(self);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_save(void* p, calldata_t*) noexcept
|
void obs::deprecated_source::handle_save(void* p, calldata_t*) noexcept
|
||||||
|
@ -65,9 +65,9 @@ try {
|
||||||
}
|
}
|
||||||
self->events.save(self);
|
self->events.save(self);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_load(void* p, calldata_t*) noexcept
|
void obs::deprecated_source::handle_load(void* p, calldata_t*) noexcept
|
||||||
|
@ -78,9 +78,9 @@ try {
|
||||||
}
|
}
|
||||||
self->events.load(self);
|
self->events.load(self);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_activate(void* p, calldata_t*) noexcept
|
void obs::deprecated_source::handle_activate(void* p, calldata_t*) noexcept
|
||||||
|
@ -91,9 +91,9 @@ try {
|
||||||
}
|
}
|
||||||
self->events.activate(self);
|
self->events.activate(self);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_deactivate(void* p, calldata_t*) noexcept
|
void obs::deprecated_source::handle_deactivate(void* p, calldata_t*) noexcept
|
||||||
|
@ -104,9 +104,9 @@ try {
|
||||||
}
|
}
|
||||||
self->events.deactivate(self);
|
self->events.deactivate(self);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_show(void* p, calldata_t*) noexcept
|
void obs::deprecated_source::handle_show(void* p, calldata_t*) noexcept
|
||||||
|
@ -117,9 +117,9 @@ try {
|
||||||
}
|
}
|
||||||
self->events.show(self);
|
self->events.show(self);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_hide(void* p, calldata_t*) noexcept
|
void obs::deprecated_source::handle_hide(void* p, calldata_t*) noexcept
|
||||||
|
@ -130,9 +130,9 @@ try {
|
||||||
}
|
}
|
||||||
self->events.hide(self);
|
self->events.hide(self);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_enable(void* p, calldata_t* calldata) noexcept
|
void obs::deprecated_source::handle_enable(void* p, calldata_t* calldata) noexcept
|
||||||
|
@ -149,9 +149,9 @@ try {
|
||||||
|
|
||||||
self->events.enable(self, enabled);
|
self->events.enable(self, enabled);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_push_to_mute_changed(void* p, calldata_t* calldata) noexcept
|
void obs::deprecated_source::handle_push_to_mute_changed(void* p, calldata_t* calldata) noexcept
|
||||||
|
@ -168,9 +168,9 @@ try {
|
||||||
|
|
||||||
self->events.push_to_mute_changed(self, enabled);
|
self->events.push_to_mute_changed(self, enabled);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_push_to_mute_delay(void* p, calldata_t* calldata) noexcept
|
void obs::deprecated_source::handle_push_to_mute_delay(void* p, calldata_t* calldata) noexcept
|
||||||
|
@ -187,9 +187,9 @@ try {
|
||||||
|
|
||||||
self->events.push_to_mute_delay(self, delay);
|
self->events.push_to_mute_delay(self, delay);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_push_to_talk_changed(void* p, calldata_t* calldata) noexcept
|
void obs::deprecated_source::handle_push_to_talk_changed(void* p, calldata_t* calldata) noexcept
|
||||||
|
@ -206,9 +206,9 @@ try {
|
||||||
|
|
||||||
self->events.push_to_talk_changed(self, enabled);
|
self->events.push_to_talk_changed(self, enabled);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_push_to_talk_delay(void* p, calldata_t* calldata) noexcept
|
void obs::deprecated_source::handle_push_to_talk_delay(void* p, calldata_t* calldata) noexcept
|
||||||
|
@ -225,9 +225,9 @@ try {
|
||||||
|
|
||||||
self->events.push_to_talk_delay(self, delay);
|
self->events.push_to_talk_delay(self, delay);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_rename(void* p, calldata_t* calldata) noexcept
|
void obs::deprecated_source::handle_rename(void* p, calldata_t* calldata) noexcept
|
||||||
|
@ -249,9 +249,9 @@ try {
|
||||||
|
|
||||||
self->events.rename(self, std::string(new_name ? new_name : ""), std::string(prev_name ? prev_name : ""));
|
self->events.rename(self, std::string(new_name ? new_name : ""), std::string(prev_name ? prev_name : ""));
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_update_properties(void* p, calldata_t*) noexcept
|
void obs::deprecated_source::handle_update_properties(void* p, calldata_t*) noexcept
|
||||||
|
@ -262,9 +262,9 @@ try {
|
||||||
}
|
}
|
||||||
self->events.update_properties(self);
|
self->events.update_properties(self);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_update_flags(void* p, calldata_t* calldata) noexcept
|
void obs::deprecated_source::handle_update_flags(void* p, calldata_t* calldata) noexcept
|
||||||
|
@ -281,9 +281,9 @@ try {
|
||||||
|
|
||||||
self->events.update_flags(self, flags);
|
self->events.update_flags(self, flags);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_mute(void* p, calldata_t* calldata) noexcept
|
void obs::deprecated_source::handle_mute(void* p, calldata_t* calldata) noexcept
|
||||||
|
@ -300,9 +300,9 @@ try {
|
||||||
|
|
||||||
self->events.mute(self, muted);
|
self->events.mute(self, muted);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_volume(void* p, calldata_t* calldata) noexcept
|
void obs::deprecated_source::handle_volume(void* p, calldata_t* calldata) noexcept
|
||||||
|
@ -321,9 +321,9 @@ try {
|
||||||
|
|
||||||
calldata_set_float(calldata, "volume", volume);
|
calldata_set_float(calldata, "volume", volume);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_audio_sync(void* p, calldata_t* calldata) noexcept
|
void obs::deprecated_source::handle_audio_sync(void* p, calldata_t* calldata) noexcept
|
||||||
|
@ -342,9 +342,9 @@ try {
|
||||||
|
|
||||||
calldata_set_int(calldata, "offset", mixers);
|
calldata_set_int(calldata, "offset", mixers);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_audio_mixers(void* p, calldata_t* calldata) noexcept
|
void obs::deprecated_source::handle_audio_mixers(void* p, calldata_t* calldata) noexcept
|
||||||
|
@ -363,9 +363,9 @@ try {
|
||||||
|
|
||||||
calldata_set_int(calldata, "mixers", mixers);
|
calldata_set_int(calldata, "mixers", mixers);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_audio_data(void* p, obs_source_t*, const audio_data* audio, bool muted) noexcept
|
void obs::deprecated_source::handle_audio_data(void* p, obs_source_t*, const audio_data* audio, bool muted) noexcept
|
||||||
|
@ -377,9 +377,9 @@ try {
|
||||||
|
|
||||||
self->events.audio_data(self, audio, muted);
|
self->events.audio_data(self, audio, muted);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_filter_add(void* p, calldata_t* calldata) noexcept
|
void obs::deprecated_source::handle_filter_add(void* p, calldata_t* calldata) noexcept
|
||||||
|
@ -396,9 +396,9 @@ try {
|
||||||
|
|
||||||
self->events.filter_add(self, filter);
|
self->events.filter_add(self, filter);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_filter_remove(void* p, calldata_t* calldata) noexcept
|
void obs::deprecated_source::handle_filter_remove(void* p, calldata_t* calldata) noexcept
|
||||||
|
@ -415,9 +415,9 @@ try {
|
||||||
|
|
||||||
self->events.filter_remove(self, filter);
|
self->events.filter_remove(self, filter);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_reorder_filters(void* p, calldata_t*) noexcept
|
void obs::deprecated_source::handle_reorder_filters(void* p, calldata_t*) noexcept
|
||||||
|
@ -428,9 +428,9 @@ try {
|
||||||
}
|
}
|
||||||
self->events.reorder_filters(self);
|
self->events.reorder_filters(self);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_transition_start(void* p, calldata_t*) noexcept
|
void obs::deprecated_source::handle_transition_start(void* p, calldata_t*) noexcept
|
||||||
|
@ -441,9 +441,9 @@ try {
|
||||||
}
|
}
|
||||||
self->events.transition_start(self);
|
self->events.transition_start(self);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_transition_video_stop(void* p, calldata_t*) noexcept
|
void obs::deprecated_source::handle_transition_video_stop(void* p, calldata_t*) noexcept
|
||||||
|
@ -454,9 +454,9 @@ try {
|
||||||
}
|
}
|
||||||
self->events.transition_video_stop(self);
|
self->events.transition_video_stop(self);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs::deprecated_source::handle_transition_stop(void* p, calldata_t*) noexcept
|
void obs::deprecated_source::handle_transition_stop(void* p, calldata_t*) noexcept
|
||||||
|
@ -467,9 +467,9 @@ try {
|
||||||
}
|
}
|
||||||
self->events.transition_stop(self);
|
self->events.transition_stop(self);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
obs::deprecated_source::~deprecated_source()
|
obs::deprecated_source::~deprecated_source()
|
||||||
|
|
|
@ -45,7 +45,7 @@ try {
|
||||||
scs_searchdata& sd = reinterpret_cast<scs_searchdata&>(*reinterpret_cast<scs_searchdata*>(searchdata));
|
scs_searchdata& sd = reinterpret_cast<scs_searchdata&>(*reinterpret_cast<scs_searchdata*>(searchdata));
|
||||||
scs_contains(sd, child);
|
scs_contains(sd, child);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool scs_enum_items_cb(obs_scene_t*, obs_sceneitem_t* item, void* searchdata) noexcept
|
static bool scs_enum_items_cb(obs_scene_t*, obs_sceneitem_t* item, void* searchdata) noexcept
|
||||||
|
@ -54,7 +54,7 @@ try {
|
||||||
obs_source_t* source = obs_sceneitem_get_source(item);
|
obs_source_t* source = obs_sceneitem_get_source(item);
|
||||||
return scs_contains(sd, source);
|
return scs_contains(sd, source);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,25 +19,33 @@
|
||||||
|
|
||||||
#include "plugin.hpp"
|
#include "plugin.hpp"
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "obs/obs-source-tracker.hpp"
|
||||||
|
|
||||||
|
//#include "encoders/ffmpeg-encoder.hpp"
|
||||||
|
|
||||||
#include "filters/filter-blur.hpp"
|
#include "filters/filter-blur.hpp"
|
||||||
#include "filters/filter-color-grade.hpp"
|
#include "filters/filter-color-grade.hpp"
|
||||||
#include "filters/filter-displacement.hpp"
|
#include "filters/filter-displacement.hpp"
|
||||||
#include "filters/filter-dynamic-mask.hpp"
|
#include "filters/filter-dynamic-mask.hpp"
|
||||||
#include "filters/filter-sdf-effects.hpp"
|
#include "filters/filter-sdf-effects.hpp"
|
||||||
//#include "filters/filter-shader.hpp"
|
|
||||||
#include "filters/filter-transform.hpp"
|
#include "filters/filter-transform.hpp"
|
||||||
#include "obs/obs-source-tracker.hpp"
|
//#include "filters/filter-shader.hpp"
|
||||||
|
|
||||||
#include "sources/source-mirror.hpp"
|
#include "sources/source-mirror.hpp"
|
||||||
#include "sources/source-shader.hpp"
|
#include "sources/source-shader.hpp"
|
||||||
|
|
||||||
MODULE_EXPORT bool obs_module_load(void)
|
MODULE_EXPORT bool obs_module_load(void)
|
||||||
try {
|
try {
|
||||||
P_LOG_INFO("Loading Version %s", STREAMEFFECTS_VERSION_STRING);
|
LOG_INFO("Loading Version %s", STREAMFX_VERSION_STRING);
|
||||||
|
|
||||||
// Initialize Source Tracker
|
// Initialize Source Tracker
|
||||||
obs::source_tracker::initialize();
|
obs::source_tracker::initialize();
|
||||||
|
|
||||||
// Initialize Filters
|
// Encoders
|
||||||
|
//encoder::ffmpeg::ffmpeg_manager::initialize();
|
||||||
|
|
||||||
|
// Filters
|
||||||
filter::blur::blur_factory::initialize();
|
filter::blur::blur_factory::initialize();
|
||||||
filter::color_grade::color_grade_factory::initialize();
|
filter::color_grade::color_grade_factory::initialize();
|
||||||
filter::displacement::displacement_factory::initialize();
|
filter::displacement::displacement_factory::initialize();
|
||||||
|
@ -46,25 +54,29 @@ try {
|
||||||
//filter::shader::shader_factory::initialize();
|
//filter::shader::shader_factory::initialize();
|
||||||
filter::transform::transform_factory::initialize();
|
filter::transform::transform_factory::initialize();
|
||||||
|
|
||||||
// Initialize Sources
|
// Sources
|
||||||
source::mirror::mirror_factory::initialize();
|
source::mirror::mirror_factory::initialize();
|
||||||
source::shader::shader_factory::initialize();
|
source::shader::shader_factory::initialize();
|
||||||
|
|
||||||
|
// Transitions
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MODULE_EXPORT void obs_module_unload(void)
|
MODULE_EXPORT void obs_module_unload(void)
|
||||||
try {
|
try {
|
||||||
P_LOG_INFO("Unloading Version %s", STREAMEFFECTS_VERSION_STRING);
|
LOG_INFO("Unloading Version %s", STREAMFX_VERSION_STRING);
|
||||||
|
|
||||||
// Clean up Sources
|
// Transitions
|
||||||
|
|
||||||
|
// Sources
|
||||||
source::mirror::mirror_factory::finalize();
|
source::mirror::mirror_factory::finalize();
|
||||||
source::shader::shader_factory::finalize();
|
source::shader::shader_factory::finalize();
|
||||||
|
|
||||||
// Clean up Filters
|
// Filters
|
||||||
filter::blur::blur_factory::finalize();
|
filter::blur::blur_factory::finalize();
|
||||||
filter::color_grade::color_grade_factory::finalize();
|
filter::color_grade::color_grade_factory::finalize();
|
||||||
filter::displacement::displacement_factory::finalize();
|
filter::displacement::displacement_factory::finalize();
|
||||||
|
@ -73,10 +85,13 @@ try {
|
||||||
//filter::shader::shader_factory::finalize();
|
//filter::shader::shader_factory::finalize();
|
||||||
filter::transform::transform_factory::finalize();
|
filter::transform::transform_factory::finalize();
|
||||||
|
|
||||||
// Clean up Source Tracker
|
// Encoders
|
||||||
|
//encoder::ffmpeg::ffmpeg_manager::finalize();
|
||||||
|
|
||||||
|
// Finalize Source Tracker
|
||||||
obs::source_tracker::finalize();
|
obs::source_tracker::finalize();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
|
@ -33,16 +33,16 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
#define P_LOG(level, ...) blog(level, "[" PLUGIN_NAME "] " __VA_ARGS__)
|
#define LOG_(level, ...) blog(level, "[" PLUGIN_NAME "] " __VA_ARGS__)
|
||||||
#define P_LOG_ERROR(...) P_LOG(LOG_ERROR, __VA_ARGS__)
|
#define LOG_ERROR(...) LOG_(LOG_ERROR, __VA_ARGS__)
|
||||||
#define P_LOG_WARNING(...) P_LOG(LOG_WARNING, __VA_ARGS__)
|
#define LOG_WARNING(...) LOG_(LOG_WARNING, __VA_ARGS__)
|
||||||
#define P_LOG_INFO(...) P_LOG(LOG_INFO, __VA_ARGS__)
|
#define LOG_INFO(...) LOG_(LOG_INFO, __VA_ARGS__)
|
||||||
#define P_LOG_DEBUG(...) P_LOG(LOG_DEBUG, __VA_ARGS__)
|
#define LOG_DEBUG(...) LOG_(LOG_DEBUG, __VA_ARGS__)
|
||||||
|
|
||||||
#ifndef __FUNCTION_NAME__
|
#ifndef __FUNCTION_NAME__
|
||||||
#ifdef WIN32 //WINDOWS
|
#ifdef WIN32 // WINDOWS
|
||||||
#define __FUNCTION_NAME__ __FUNCTION__
|
#define __FUNCTION_NAME__ __FUNCTION__
|
||||||
#else //*NIX
|
#else // *NIX
|
||||||
#define __FUNCTION_NAME__ __func__
|
#define __FUNCTION_NAME__ __func__
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -63,7 +63,9 @@
|
||||||
#define ST_SCALING_BOUNDS_FILLHEIGHT ST_SCALING ".Bounds.FillHeight"
|
#define ST_SCALING_BOUNDS_FILLHEIGHT ST_SCALING ".Bounds.FillHeight"
|
||||||
#define ST_SCALING_ALIGNMENT ST_SCALING ".Alignment"
|
#define ST_SCALING_ALIGNMENT ST_SCALING ".Alignment"
|
||||||
|
|
||||||
void source::mirror::mirror_instance::release()
|
using namespace source;
|
||||||
|
|
||||||
|
void mirror::mirror_instance::release()
|
||||||
{
|
{
|
||||||
_source_item.reset();
|
_source_item.reset();
|
||||||
if (_source) {
|
if (_source) {
|
||||||
|
@ -74,7 +76,7 @@ void source::mirror::mirror_instance::release()
|
||||||
_source_name.clear();
|
_source_name.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void source::mirror::mirror_instance::acquire(std::string source_name)
|
void mirror::mirror_instance::acquire(std::string source_name)
|
||||||
{
|
{
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
@ -99,12 +101,12 @@ void source::mirror::mirror_instance::acquire(std::string source_name)
|
||||||
_source_item = std::shared_ptr<obs_sceneitem_t>(item, [](obs_sceneitem_t* ref) { obs_sceneitem_remove(ref); });
|
_source_item = std::shared_ptr<obs_sceneitem_t>(item, [](obs_sceneitem_t* ref) { obs_sceneitem_remove(ref); });
|
||||||
|
|
||||||
// And let's hook up all our events too.
|
// And let's hook up all our events too.
|
||||||
_source->events.rename.add(std::bind(&source::mirror::mirror_instance::on_source_rename, this, _1, _2, _3));
|
_source->events.rename.add(std::bind(&mirror::mirror_instance::on_source_rename, this, _1, _2, _3));
|
||||||
if ((obs_source_get_output_flags(this->_source->get()) & OBS_SOURCE_AUDIO) != 0)
|
if ((obs_source_get_output_flags(this->_source->get()) & OBS_SOURCE_AUDIO) != 0)
|
||||||
_source->events.audio_data.add(std::bind(&source::mirror::mirror_instance::on_audio_data, this, _1, _2, _3));
|
_source->events.audio_data.add(std::bind(&mirror::mirror_instance::on_audio_data, this, _1, _2, _3));
|
||||||
}
|
}
|
||||||
|
|
||||||
source::mirror::mirror_instance::mirror_instance(obs_data_t* settings, obs_source_t* self)
|
mirror::mirror_instance::mirror_instance(obs_data_t* settings, obs_source_t* self)
|
||||||
: obs::source_instance(settings, self), _source(), _source_name(), _audio_enabled(), _audio_layout(),
|
: obs::source_instance(settings, self), _source(), _source_name(), _audio_enabled(), _audio_layout(),
|
||||||
_audio_kill_thread(), _audio_have_output(), _rescale_enabled(), _rescale_width(), _rescale_height(),
|
_audio_kill_thread(), _audio_have_output(), _rescale_enabled(), _rescale_width(), _rescale_height(),
|
||||||
_rescale_keep_orig_size(), _rescale_type(), _rescale_bounds(), _rescale_alignment(), _cache_enabled(),
|
_rescale_keep_orig_size(), _rescale_type(), _rescale_bounds(), _rescale_alignment(), _cache_enabled(),
|
||||||
|
@ -119,12 +121,12 @@ source::mirror::mirror_instance::mirror_instance(obs_data_t* settings, obs_sourc
|
||||||
|
|
||||||
// Spawn Audio Thread
|
// Spawn Audio Thread
|
||||||
/// ToDo: Use ThreadPool for this?
|
/// ToDo: Use ThreadPool for this?
|
||||||
_audio_thread = std::thread(std::bind(&source::mirror::mirror_instance::audio_output_cb, this));
|
_audio_thread = std::thread(std::bind(&mirror::mirror_instance::audio_output_cb, this));
|
||||||
|
|
||||||
update(settings);
|
update(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
source::mirror::mirror_instance::~mirror_instance()
|
mirror::mirror_instance::~mirror_instance()
|
||||||
{
|
{
|
||||||
release();
|
release();
|
||||||
|
|
||||||
|
@ -142,12 +144,12 @@ source::mirror::mirror_instance::~mirror_instance()
|
||||||
_scene.reset();
|
_scene.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t source::mirror::mirror_instance::get_width()
|
uint32_t mirror::mirror_instance::get_width()
|
||||||
{
|
{
|
||||||
return _source_size.first;
|
return _source_size.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t source::mirror::mirror_instance::get_height()
|
uint32_t mirror::mirror_instance::get_height()
|
||||||
{
|
{
|
||||||
return _source_size.second;
|
return _source_size.second;
|
||||||
}
|
}
|
||||||
|
@ -160,15 +162,15 @@ static void convert_config(obs_data_t* data)
|
||||||
case 0:
|
case 0:
|
||||||
obs_data_set_int(data, ST_SOURCE_AUDIO_LAYOUT, obs_data_get_int(data, "Source.Mirror.Audio.Layout"));
|
obs_data_set_int(data, ST_SOURCE_AUDIO_LAYOUT, obs_data_get_int(data, "Source.Mirror.Audio.Layout"));
|
||||||
obs_data_unset_user_value(data, "Source.Mirror.Audio.Layout");
|
obs_data_unset_user_value(data, "Source.Mirror.Audio.Layout");
|
||||||
case STREAMEFFECTS_VERSION:
|
case STREAMFX_VERSION:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_data_set_int(data, S_VERSION, STREAMEFFECTS_VERSION);
|
obs_data_set_int(data, S_VERSION, STREAMFX_VERSION);
|
||||||
obs_data_set_string(data, S_COMMIT, STREAMEFFECTS_COMMIT);
|
obs_data_set_string(data, S_COMMIT, STREAMFX_COMMIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void source::mirror::mirror_instance::update(obs_data_t* data)
|
void mirror::mirror_instance::update(obs_data_t* data)
|
||||||
{
|
{
|
||||||
convert_config(data);
|
convert_config(data);
|
||||||
|
|
||||||
|
@ -222,19 +224,19 @@ void source::mirror::mirror_instance::update(obs_data_t* data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void source::mirror::mirror_instance::load(obs_data_t* data)
|
void mirror::mirror_instance::load(obs_data_t* data)
|
||||||
{
|
{
|
||||||
this->update(data);
|
this->update(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void source::mirror::mirror_instance::save(obs_data_t* data)
|
void mirror::mirror_instance::save(obs_data_t* data)
|
||||||
{
|
{
|
||||||
if (_source) {
|
if (_source) {
|
||||||
obs_data_set_string(data, ST_SOURCE, obs_source_get_name(_source->get()));
|
obs_data_set_string(data, ST_SOURCE, obs_source_get_name(_source->get()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void source::mirror::mirror_instance::video_tick(float time)
|
void mirror::mirror_instance::video_tick(float time)
|
||||||
{
|
{
|
||||||
if (_source && ((obs_source_get_output_flags(_source->get()) & OBS_SOURCE_VIDEO) != 0)) {
|
if (_source && ((obs_source_get_output_flags(_source->get()) & OBS_SOURCE_VIDEO) != 0)) {
|
||||||
if (_rescale_keep_orig_size || !_rescale_enabled) {
|
if (_rescale_keep_orig_size || !_rescale_enabled) {
|
||||||
|
@ -272,7 +274,7 @@ void source::mirror::mirror_instance::video_tick(float time)
|
||||||
_cache_rendered = false;
|
_cache_rendered = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void source::mirror::mirror_instance::video_render(gs_effect_t* effect)
|
void mirror::mirror_instance::video_render(gs_effect_t* effect)
|
||||||
{
|
{
|
||||||
if (!_source || !_source_item)
|
if (!_source || !_source_item)
|
||||||
return;
|
return;
|
||||||
|
@ -314,7 +316,7 @@ void source::mirror::mirror_instance::video_render(gs_effect_t* effect)
|
||||||
GS_DEBUG_MARKER_END();
|
GS_DEBUG_MARKER_END();
|
||||||
}
|
}
|
||||||
|
|
||||||
void source::mirror::mirror_instance::audio_output_cb() noexcept
|
void mirror::mirror_instance::audio_output_cb() noexcept
|
||||||
try {
|
try {
|
||||||
std::unique_lock<std::mutex> ulock(this->_audio_lock_outputter);
|
std::unique_lock<std::mutex> ulock(this->_audio_lock_outputter);
|
||||||
|
|
||||||
|
@ -347,12 +349,12 @@ try {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void source::mirror::mirror_instance::enum_active_sources(obs_source_enum_proc_t enum_callback, void* param)
|
void mirror::mirror_instance::enum_active_sources(obs_source_enum_proc_t enum_callback, void* param)
|
||||||
{
|
{
|
||||||
/* if (_scene) {
|
/* if (_scene) {
|
||||||
enum_callback(_self, _scene.get(), param);
|
enum_callback(_self, _scene.get(), param);
|
||||||
|
@ -362,7 +364,7 @@ void source::mirror::mirror_instance::enum_active_sources(obs_source_enum_proc_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void source::mirror::mirror_instance::enum_all_sources(obs_source_enum_proc_t enum_callback, void* param)
|
void mirror::mirror_instance::enum_all_sources(obs_source_enum_proc_t enum_callback, void* param)
|
||||||
{
|
{
|
||||||
/* if (_scene) {
|
/* if (_scene) {
|
||||||
enum_callback(_self, _scene.get(), param);
|
enum_callback(_self, _scene.get(), param);
|
||||||
|
@ -372,12 +374,12 @@ void source::mirror::mirror_instance::enum_all_sources(obs_source_enum_proc_t en
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void source::mirror::mirror_instance::on_source_rename(obs::deprecated_source* source, std::string, std::string)
|
void mirror::mirror_instance::on_source_rename(obs::deprecated_source* source, std::string, std::string)
|
||||||
{
|
{
|
||||||
obs_source_save(_self);
|
obs_source_save(_self);
|
||||||
}
|
}
|
||||||
|
|
||||||
void source::mirror::mirror_instance::on_audio_data(obs::deprecated_source*, const audio_data* audio, bool)
|
void mirror::mirror_instance::on_audio_data(obs::deprecated_source*, const audio_data* audio, bool)
|
||||||
{
|
{
|
||||||
if (!this->_audio_enabled) {
|
if (!this->_audio_enabled) {
|
||||||
return;
|
return;
|
||||||
|
@ -443,9 +445,9 @@ void source::mirror::mirror_instance::on_audio_data(obs::deprecated_source*, con
|
||||||
this->_audio_notify.notify_all();
|
this->_audio_notify.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<source::mirror::mirror_factory> source::mirror::mirror_factory::factory_instance;
|
std::shared_ptr<mirror::mirror_factory> mirror::mirror_factory::factory_instance;
|
||||||
|
|
||||||
source::mirror::mirror_factory::mirror_factory()
|
mirror::mirror_factory::mirror_factory()
|
||||||
{
|
{
|
||||||
_info.id = "obs-stream-effects-source-mirror";
|
_info.id = "obs-stream-effects-source-mirror";
|
||||||
_info.type = OBS_SOURCE_TYPE_INPUT;
|
_info.type = OBS_SOURCE_TYPE_INPUT;
|
||||||
|
@ -454,14 +456,14 @@ source::mirror::mirror_factory::mirror_factory()
|
||||||
finish_setup();
|
finish_setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
source::mirror::mirror_factory::~mirror_factory() {}
|
mirror::mirror_factory::~mirror_factory() {}
|
||||||
|
|
||||||
const char* source::mirror::mirror_factory::get_name()
|
const char* mirror::mirror_factory::get_name()
|
||||||
{
|
{
|
||||||
return D_TRANSLATE(ST);
|
return D_TRANSLATE(ST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void source::mirror::mirror_factory::get_defaults2(obs_data_t* data)
|
void mirror::mirror_factory::get_defaults2(obs_data_t* data)
|
||||||
{
|
{
|
||||||
obs_data_set_default_string(data, ST_SOURCE, "");
|
obs_data_set_default_string(data, ST_SOURCE, "");
|
||||||
obs_data_set_default_bool(data, ST_SOURCE_AUDIO, false);
|
obs_data_set_default_bool(data, ST_SOURCE_AUDIO, false);
|
||||||
|
@ -532,14 +534,14 @@ try {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||||
return false;
|
return false;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_properties_t* source::mirror::mirror_factory::get_properties2(source::mirror::mirror_instance* data)
|
obs_properties_t* mirror::mirror_factory::get_properties2(mirror::mirror_instance* data)
|
||||||
{
|
{
|
||||||
obs_properties_t* pr = obs_properties_create();
|
obs_properties_t* pr = obs_properties_create();
|
||||||
obs_property_t* p = nullptr;
|
obs_property_t* p = nullptr;
|
||||||
|
|
|
@ -41,108 +41,105 @@
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace source {
|
namespace source::mirror {
|
||||||
namespace mirror {
|
struct mirror_audio_data {
|
||||||
struct mirror_audio_data {
|
obs_source_audio audio = {};
|
||||||
obs_source_audio audio = {};
|
std::vector<std::vector<float_t>> data;
|
||||||
std::vector<std::vector<float_t>> data;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
class mirror_instance : public obs::source_instance {
|
class mirror_instance : public obs::source_instance {
|
||||||
// Source
|
// Source
|
||||||
std::shared_ptr<obs::deprecated_source> _source;
|
std::shared_ptr<obs::deprecated_source> _source;
|
||||||
std::string _source_name;
|
std::string _source_name;
|
||||||
|
|
||||||
// Cached Data
|
// Cached Data
|
||||||
std::pair<uint32_t, uint32_t> _source_size;
|
std::pair<uint32_t, uint32_t> _source_size;
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
bool _audio_enabled;
|
bool _audio_enabled;
|
||||||
speaker_layout _audio_layout;
|
speaker_layout _audio_layout;
|
||||||
std::condition_variable _audio_notify;
|
std::condition_variable _audio_notify;
|
||||||
std::thread _audio_thread;
|
std::thread _audio_thread;
|
||||||
bool _audio_kill_thread;
|
bool _audio_kill_thread;
|
||||||
bool _audio_have_output;
|
bool _audio_have_output;
|
||||||
std::mutex _audio_lock_outputter;
|
std::mutex _audio_lock_outputter;
|
||||||
std::mutex _audio_lock_capturer;
|
std::mutex _audio_lock_capturer;
|
||||||
std::queue<std::shared_ptr<mirror_audio_data>> _audio_data_queue;
|
std::queue<std::shared_ptr<mirror_audio_data>> _audio_data_queue;
|
||||||
std::queue<std::shared_ptr<mirror_audio_data>> _audio_data_free_queue;
|
std::queue<std::shared_ptr<mirror_audio_data>> _audio_data_free_queue;
|
||||||
|
|
||||||
// Scaling
|
// Scaling
|
||||||
bool _rescale_enabled;
|
bool _rescale_enabled;
|
||||||
uint32_t _rescale_width;
|
uint32_t _rescale_width;
|
||||||
uint32_t _rescale_height;
|
uint32_t _rescale_height;
|
||||||
bool _rescale_keep_orig_size;
|
bool _rescale_keep_orig_size;
|
||||||
obs_scale_type _rescale_type;
|
obs_scale_type _rescale_type;
|
||||||
obs_bounds_type _rescale_bounds;
|
obs_bounds_type _rescale_bounds;
|
||||||
uint32_t _rescale_alignment;
|
uint32_t _rescale_alignment;
|
||||||
|
|
||||||
// Caching
|
// Caching
|
||||||
bool _cache_enabled;
|
bool _cache_enabled;
|
||||||
bool _cache_rendered;
|
bool _cache_rendered;
|
||||||
std::shared_ptr<gfx::source_texture> _cache_renderer;
|
std::shared_ptr<gfx::source_texture> _cache_renderer;
|
||||||
std::shared_ptr<gs::texture> _cache_texture;
|
std::shared_ptr<gs::texture> _cache_texture;
|
||||||
|
|
||||||
// Scene
|
// Scene
|
||||||
std::shared_ptr<obs_source_t> _scene;
|
std::shared_ptr<obs_source_t> _scene;
|
||||||
std::shared_ptr<obs_sceneitem_t> _source_item;
|
std::shared_ptr<obs_sceneitem_t> _source_item;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void release();
|
void release();
|
||||||
void acquire(std::string source_name);
|
void acquire(std::string source_name);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
mirror_instance(obs_data_t* settings, obs_source_t* self);
|
mirror_instance(obs_data_t* settings, obs_source_t* self);
|
||||||
virtual ~mirror_instance();
|
virtual ~mirror_instance();
|
||||||
|
|
||||||
virtual uint32_t get_width() override;
|
virtual uint32_t get_width() override;
|
||||||
virtual uint32_t get_height() override;
|
virtual uint32_t get_height() override;
|
||||||
|
|
||||||
virtual void update(obs_data_t*) override;
|
virtual void update(obs_data_t*) override;
|
||||||
virtual void load(obs_data_t*) override;
|
virtual void load(obs_data_t*) override;
|
||||||
virtual void save(obs_data_t*) override;
|
virtual void save(obs_data_t*) override;
|
||||||
|
|
||||||
virtual void video_tick(float) override;
|
virtual void video_tick(float) override;
|
||||||
virtual void video_render(gs_effect_t*) override;
|
virtual void video_render(gs_effect_t*) override;
|
||||||
|
|
||||||
virtual void enum_active_sources(obs_source_enum_proc_t, void*) override;
|
virtual void enum_active_sources(obs_source_enum_proc_t, void*) override;
|
||||||
virtual void enum_all_sources(obs_source_enum_proc_t, void*) override;
|
virtual void enum_all_sources(obs_source_enum_proc_t, void*) override;
|
||||||
|
|
||||||
void audio_output_cb() noexcept;
|
void audio_output_cb() noexcept;
|
||||||
|
|
||||||
void on_source_rename(obs::deprecated_source* source, std::string new_name, std::string old_name);
|
void on_source_rename(obs::deprecated_source* source, std::string new_name, std::string old_name);
|
||||||
void on_audio_data(obs::deprecated_source* source, const audio_data* audio, bool muted);
|
void on_audio_data(obs::deprecated_source* source, const audio_data* audio, bool muted);
|
||||||
};
|
};
|
||||||
|
|
||||||
class mirror_factory
|
class mirror_factory : public obs::source_factory<source::mirror::mirror_factory, source::mirror::mirror_instance> {
|
||||||
: public obs::source_factory<source::mirror::mirror_factory, source::mirror::mirror_instance> {
|
static std::shared_ptr<source::mirror::mirror_factory> factory_instance;
|
||||||
static std::shared_ptr<source::mirror::mirror_factory> factory_instance;
|
|
||||||
|
|
||||||
public: // Singleton
|
public: // Singleton
|
||||||
static void initialize()
|
static void initialize()
|
||||||
{
|
{
|
||||||
factory_instance = std::make_shared<source::mirror::mirror_factory>();
|
factory_instance = std::make_shared<source::mirror::mirror_factory>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void finalize()
|
static void finalize()
|
||||||
{
|
{
|
||||||
factory_instance.reset();
|
factory_instance.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::shared_ptr<mirror_factory> get()
|
static std::shared_ptr<mirror_factory> get()
|
||||||
{
|
{
|
||||||
return factory_instance;
|
return factory_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
mirror_factory();
|
mirror_factory();
|
||||||
virtual ~mirror_factory() override;
|
virtual ~mirror_factory() override;
|
||||||
|
|
||||||
virtual const char* get_name() override;
|
virtual const char* get_name() override;
|
||||||
|
|
||||||
virtual void get_defaults2(obs_data_t* data) override;
|
virtual void get_defaults2(obs_data_t* data) override;
|
||||||
|
|
||||||
virtual obs_properties_t* get_properties2(source::mirror::mirror_instance* data) override;
|
virtual obs_properties_t* get_properties2(source::mirror::mirror_instance* data) override;
|
||||||
};
|
};
|
||||||
} // namespace mirror
|
} // namespace source::mirror
|
||||||
}; // namespace source
|
|
||||||
|
|
|
@ -24,7 +24,9 @@
|
||||||
|
|
||||||
#define ST "Source.Shader"
|
#define ST "Source.Shader"
|
||||||
|
|
||||||
source::shader::shader_instance::shader_instance(obs_data_t* data, obs_source_t* self)
|
using namespace source;
|
||||||
|
|
||||||
|
shader::shader_instance::shader_instance(obs_data_t* data, obs_source_t* self)
|
||||||
: obs::source_instance(data, self), _is_main(false)
|
: obs::source_instance(data, self), _is_main(false)
|
||||||
{
|
{
|
||||||
_fx = std::make_shared<gfx::shader::shader>(self, gfx::shader::shader_mode::Source);
|
_fx = std::make_shared<gfx::shader::shader>(self, gfx::shader::shader_mode::Source);
|
||||||
|
@ -32,34 +34,34 @@ source::shader::shader_instance::shader_instance(obs_data_t* data, obs_source_t*
|
||||||
update(data);
|
update(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
source::shader::shader_instance::~shader_instance() {}
|
shader::shader_instance::~shader_instance() {}
|
||||||
|
|
||||||
uint32_t source::shader::shader_instance::get_width()
|
uint32_t shader::shader_instance::get_width()
|
||||||
{
|
{
|
||||||
return _fx->width();
|
return _fx->width();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t source::shader::shader_instance::get_height()
|
uint32_t shader::shader_instance::get_height()
|
||||||
{
|
{
|
||||||
return _fx->height();
|
return _fx->height();
|
||||||
}
|
}
|
||||||
|
|
||||||
void source::shader::shader_instance::properties(obs_properties_t* props)
|
void shader::shader_instance::properties(obs_properties_t* props)
|
||||||
{
|
{
|
||||||
_fx->properties(props);
|
_fx->properties(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
void source::shader::shader_instance::load(obs_data_t* data)
|
void shader::shader_instance::load(obs_data_t* data)
|
||||||
{
|
{
|
||||||
_fx->update(data);
|
_fx->update(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void source::shader::shader_instance::update(obs_data_t* data)
|
void shader::shader_instance::update(obs_data_t* data)
|
||||||
{
|
{
|
||||||
_fx->update(data);
|
_fx->update(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void source::shader::shader_instance::video_tick(float_t sec_since_last)
|
void shader::shader_instance::video_tick(float_t sec_since_last)
|
||||||
{
|
{
|
||||||
if (_fx->tick(sec_since_last)) {
|
if (_fx->tick(sec_since_last)) {
|
||||||
obs_data_t* data = obs_source_get_settings(_self);
|
obs_data_t* data = obs_source_get_settings(_self);
|
||||||
|
@ -70,7 +72,7 @@ void source::shader::shader_instance::video_tick(float_t sec_since_last)
|
||||||
_is_main = true;
|
_is_main = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void source::shader::shader_instance::video_render(gs_effect_t* effect)
|
void shader::shader_instance::video_render(gs_effect_t* effect)
|
||||||
{
|
{
|
||||||
if (!_fx) {
|
if (!_fx) {
|
||||||
return;
|
return;
|
||||||
|
@ -86,9 +88,9 @@ void source::shader::shader_instance::video_render(gs_effect_t* effect)
|
||||||
_fx->render();
|
_fx->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<source::shader::shader_factory> source::shader::shader_factory::factory_instance = nullptr;
|
std::shared_ptr<shader::shader_factory> shader::shader_factory::factory_instance = nullptr;
|
||||||
|
|
||||||
source::shader::shader_factory::shader_factory()
|
shader::shader_factory::shader_factory()
|
||||||
{
|
{
|
||||||
_info.id = "obs-stream-effects-source-shader";
|
_info.id = "obs-stream-effects-source-shader";
|
||||||
_info.type = OBS_SOURCE_TYPE_INPUT;
|
_info.type = OBS_SOURCE_TYPE_INPUT;
|
||||||
|
@ -97,16 +99,16 @@ source::shader::shader_factory::shader_factory()
|
||||||
finish_setup();
|
finish_setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
source::shader::shader_factory::~shader_factory() {}
|
shader::shader_factory::~shader_factory() {}
|
||||||
|
|
||||||
const char* source::shader::shader_factory::get_name()
|
const char* shader::shader_factory::get_name()
|
||||||
{
|
{
|
||||||
return D_TRANSLATE(ST);
|
return D_TRANSLATE(ST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void source::shader::shader_factory::get_defaults2(obs_data_t* data) {}
|
void shader::shader_factory::get_defaults2(obs_data_t* data) {}
|
||||||
|
|
||||||
obs_properties_t* source::shader::shader_factory::get_properties2(source::shader::shader_instance* data)
|
obs_properties_t* shader::shader_factory::get_properties2(shader::shader_instance* data)
|
||||||
{
|
{
|
||||||
auto pr = obs_properties_create();
|
auto pr = obs_properties_create();
|
||||||
obs_properties_set_param(pr, data, nullptr);
|
obs_properties_set_param(pr, data, nullptr);
|
||||||
|
|
|
@ -28,58 +28,55 @@ extern "C" {
|
||||||
#include <obs.h>
|
#include <obs.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace source {
|
namespace source::shader {
|
||||||
namespace shader {
|
class shader_instance : public obs::source_instance {
|
||||||
class shader_instance : public obs::source_instance {
|
std::shared_ptr<gfx::shader::shader> _fx;
|
||||||
std::shared_ptr<gfx::shader::shader> _fx;
|
|
||||||
|
|
||||||
bool _is_main;
|
bool _is_main;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
shader_instance(obs_data_t* data, obs_source_t* self);
|
shader_instance(obs_data_t* data, obs_source_t* self);
|
||||||
virtual ~shader_instance();
|
virtual ~shader_instance();
|
||||||
|
|
||||||
virtual uint32_t get_width() override;
|
virtual uint32_t get_width() override;
|
||||||
virtual uint32_t get_height() override;
|
virtual uint32_t get_height() override;
|
||||||
|
|
||||||
void properties(obs_properties_t* props);
|
void properties(obs_properties_t* props);
|
||||||
|
|
||||||
virtual void load(obs_data_t* data) override;
|
virtual void load(obs_data_t* data) override;
|
||||||
virtual void update(obs_data_t* data) override;
|
virtual void update(obs_data_t* data) override;
|
||||||
|
|
||||||
virtual void video_tick(float_t sec_since_last) override;
|
virtual void video_tick(float_t sec_since_last) override;
|
||||||
virtual void video_render(gs_effect_t* effect) override;
|
virtual void video_render(gs_effect_t* effect) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class shader_factory
|
class shader_factory : public obs::source_factory<source::shader::shader_factory, source::shader::shader_instance> {
|
||||||
: public obs::source_factory<source::shader::shader_factory, source::shader::shader_instance> {
|
static std::shared_ptr<source::shader::shader_factory> factory_instance;
|
||||||
static std::shared_ptr<source::shader::shader_factory> factory_instance;
|
|
||||||
|
|
||||||
public: // Singleton
|
public: // Singleton
|
||||||
static void initialize()
|
static void initialize()
|
||||||
{
|
{
|
||||||
factory_instance = std::make_shared<source::shader::shader_factory>();
|
factory_instance = std::make_shared<source::shader::shader_factory>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void finalize()
|
static void finalize()
|
||||||
{
|
{
|
||||||
factory_instance.reset();
|
factory_instance.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::shared_ptr<shader_factory> get()
|
static std::shared_ptr<shader_factory> get()
|
||||||
{
|
{
|
||||||
return factory_instance;
|
return factory_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
shader_factory();
|
shader_factory();
|
||||||
virtual ~shader_factory();
|
virtual ~shader_factory();
|
||||||
|
|
||||||
virtual const char* get_name() override;
|
virtual const char* get_name() override;
|
||||||
|
|
||||||
virtual void get_defaults2(obs_data_t* data) override;
|
virtual void get_defaults2(obs_data_t* data) override;
|
||||||
|
|
||||||
virtual obs_properties_t* get_properties2(source::shader::shader_instance* data) override;
|
virtual obs_properties_t* get_properties2(source::shader::shader_instance* data) override;
|
||||||
};
|
};
|
||||||
} // namespace shader
|
} // namespace source::shader
|
||||||
} // namespace source
|
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
|
|
||||||
#define S_ADVANCED "Advanced"
|
#define S_ADVANCED "Advanced"
|
||||||
|
|
||||||
|
#define S_STATE_DEFAULT "State.Default"
|
||||||
#define S_STATE_DISABLED "State.Disabled"
|
#define S_STATE_DISABLED "State.Disabled"
|
||||||
#define S_STATE_ENABLED "State.Enabled"
|
#define S_STATE_ENABLED "State.Enabled"
|
||||||
#define S_STATE_MANUAL "State.Manual"
|
#define S_STATE_MANUAL "State.Manual"
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4201)
|
#pragma warning(disable : 4201)
|
||||||
|
#pragma warning(disable : 5039)
|
||||||
#endif
|
#endif
|
||||||
#include <obs.h>
|
#include <obs.h>
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
@ -82,3 +83,12 @@ const char* obs_module_recursive_text(const char* to_translate, size_t depth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
obs_property_t* util::obs_properties_add_tristate(obs_properties_t* props, const char* name, const char* desc)
|
||||||
|
{
|
||||||
|
obs_property_t* p = obs_properties_add_list(props, name, desc, OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||||
|
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), -1);
|
||||||
|
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DISABLED), 0);
|
||||||
|
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_ENABLED), 1);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
|
@ -76,4 +76,51 @@ namespace util {
|
||||||
{
|
{
|
||||||
return obs_get_version() < MAKE_SEMANTIC_VERSION(24, 0, 0);
|
return obs_get_version() < MAKE_SEMANTIC_VERSION(24, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct obs_graphics {
|
||||||
|
obs_graphics()
|
||||||
|
{
|
||||||
|
obs_enter_graphics();
|
||||||
|
}
|
||||||
|
~obs_graphics()
|
||||||
|
{
|
||||||
|
obs_leave_graphics();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
obs_property_t* obs_properties_add_tristate(obs_properties_t* props, const char* name, const char* desc);
|
||||||
|
|
||||||
|
inline bool is_tristate_enabled(int64_t tristate)
|
||||||
|
{
|
||||||
|
return tristate == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_tristate_disabled(int64_t tristate)
|
||||||
|
{
|
||||||
|
return tristate == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_tristate_default(int64_t tristate)
|
||||||
|
{
|
||||||
|
return tristate == -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
uint32_t color;
|
||||||
|
struct {
|
||||||
|
uint8_t r;
|
||||||
|
uint8_t g;
|
||||||
|
uint8_t b;
|
||||||
|
uint8_t a;
|
||||||
|
};
|
||||||
|
} rgba32;
|
||||||
|
typedef union {
|
||||||
|
uint32_t color;
|
||||||
|
struct {
|
||||||
|
uint8_t a;
|
||||||
|
uint8_t r;
|
||||||
|
uint8_t g;
|
||||||
|
uint8_t b;
|
||||||
|
};
|
||||||
|
} argb32;
|
||||||
} // namespace util
|
} // namespace util
|
||||||
|
|
Loading…
Reference in a new issue