project: Merged FFmpeg Encoders Step 2

This commit is contained in:
Michael Fabian 'Xaymar' Dirks 2020-01-13 22:40:15 +01:00
parent 3eea289679
commit 0a16ce07dc
61 changed files with 1979 additions and 3442 deletions

View file

@ -397,14 +397,14 @@ set(PROJECT_PRIVATE_SOURCE
"${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.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.cpp"
"${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-tracker.hpp"
"${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
"${PROJECT_SOURCE_DIR}/source/sources/source-mirror.hpp"
@ -430,7 +430,7 @@ set(PROJECT_PRIVATE_SOURCE
# Transitions
# ffmpeg
# FFmpeg
"${PROJECT_SOURCE_DIR}/source/ffmpeg/avframe-queue.cpp"
"${PROJECT_SOURCE_DIR}/source/ffmpeg/avframe-queue.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/hwapi/base.hpp"
"${PROJECT_SOURCE_DIR}/source/ffmpeg/hwapi/base.cpp"
"${PROJECT_SOURCE_DIR}/source/ffmpeg/hwapi/d3d11.hpp"
"${PROJECT_SOURCE_DIR}/source/ffmpeg/hwapi/d3d11.cpp"
"${PROJECT_SOURCE_DIR}/source/ffmpeg/hwapi/d3d11.hpp"
"${PROJECT_SOURCE_DIR}/source/ffmpeg/hwapi/d3d11.cpp"
# Encoders
"${PROJECT_SOURCE_DIR}/source/encoders/encoder.hpp"
"${PROJECT_SOURCE_DIR}/source/encoders/encoder.cpp"
"${PROJECT_SOURCE_DIR}/source/encoders/ffmpeg-encoder.hpp"
"${PROJECT_SOURCE_DIR}/source/encoders/ffmpeg-encoder.cpp"
# Encoders/Codecs
"${PROJECT_SOURCE_DIR}/source/encoders/codecs/hevc.hpp"
"${PROJECT_SOURCE_DIR}/source/encoders/codecs/hevc.cpp"

View file

@ -17,23 +17,18 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef STREAMEFFECTS_VERSION_HPP
#define STREAMEFFECTS_VERSION_HPP
#pragma once
#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 STREAMEFFECTS_MASK_UPDATE 0xFFFFFFFFFFFF0000ull
#define STREAMFX_MASK_COMPAT 0xFFFFFFFF00000000ull
#define STREAMFX_MASK_UPDATE 0xFFFFFFFFFFFF0000ull
#define STREAMEFFECTS_COMMIT "@PROJECT_COMMIT@"
#define STREAMEFFECTS_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define STREAMEFFECTS_VERSION_MINOR @PROJECT_VERSION_MINOR@
#define STREAMEFFECTS_VERSION_PATCH @PROJECT_VERSION_PATCH@
#define STREAMEFFECTS_VERSION_BUILD @PROJECT_VERSION_TWEAK@
#define STREAMEFFECTS_VERSION STREAMEFFECTS_MAKE_VERSION(STREAMEFFECTS_VERSION_MAJOR, STREAMEFFECTS_VERSION_MINOR, STREAMEFFECTS_VERSION_PATCH, STREAMEFFECTS_VERSION_BUILD)
#define STREAMEFFECTS_VERSION_STRING "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.@PROJECT_VERSION_TWEAK@-@PROJECT_COMMIT@"
#endif STREAMEFFECTS_VERSION_HPP
#define STREAMFX_COMMIT "@PROJECT_COMMIT@"
#define STREAMFX_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define STREAMFX_VERSION_MINOR @PROJECT_VERSION_MINOR@
#define STREAMFX_VERSION_PATCH @PROJECT_VERSION_PATCH@
#define STREAMFX_VERSION_BUILD @PROJECT_VERSION_TWEAK@
#define STREAMFX_VERSION STREAMFX_MAKE_VERSION(STREAMFX_VERSION_MAJOR, STREAMFX_VERSION_MINOR, STREAMFX_VERSION_PATCH, STREAMFX_VERSION_BUILD)
#define STREAMFX_VERSION_STRING "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.@PROJECT_VERSION_TWEAK@-@PROJECT_COMMIT@"

View file

@ -23,6 +23,7 @@ State.Disabled="Disabled"
State.Enabled="Enabled"
State.Manual="Manual"
State.Automatic="Automatic"
State.Default="Default"
# Blur
Blur.Type.Box="Box"
@ -333,3 +334,141 @@ Source.Mirror.Scaling.Alignment.Description="How should the source be aligned wi
# Source - 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."

View file

@ -27,41 +27,37 @@
#define P_H264_PROFILE "Codec.H264.Profile"
#define P_H264_LEVEL "Codec.H264.Level"
namespace obsffmpeg {
namespace codecs {
namespace h264 {
enum class profile {
CONSTRAINED_BASELINE,
BASELINE,
MAIN,
HIGH,
HIGH444_PREDICTIVE,
UNKNOWN = -1,
};
namespace encoder::codec::h264 {
enum class profile {
CONSTRAINED_BASELINE,
BASELINE,
MAIN,
HIGH,
HIGH444_PREDICTIVE,
UNKNOWN = -1,
};
enum class level {
L1_0 = 10,
L1_0b,
L1_1,
L1_2,
L1_3,
L2_0 = 20,
L2_1,
L2_2,
L3_0 = 30,
L3_1,
L3_2,
L4_0 = 40,
L4_1,
L4_2,
L5_0 = 50,
L5_1,
L5_2,
L6_0 = 60,
L6_1,
L6_2,
UNKNOWN = -1,
};
} // namespace h264
} // namespace codecs
} // namespace obsffmpeg
enum class level {
L1_0 = 10,
L1_0b,
L1_1,
L1_2,
L1_3,
L2_0 = 20,
L2_1,
L2_2,
L3_0 = 30,
L3_1,
L3_2,
L4_0 = 40,
L4_1,
L4_2,
L5_0 = 50,
L5_1,
L5_2,
L6_0 = 60,
L6_1,
L6_2,
UNKNOWN = -1,
};
} // namespace encoder::codec::h264

View file

@ -22,6 +22,8 @@
#include "hevc.hpp"
#include "utility.hpp"
using namespace encoder::codec;
enum class nal_unit_type : uint8_t { // 6 bits
TRAIL_N = 0,
TRAIL_R = 1,
@ -104,7 +106,7 @@ struct hevc_nal {
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)
return false;
@ -138,14 +140,14 @@ size_t get_nal_size(uint8_t* data, uint8_t* end)
{
uint8_t* ptr = data + 4;
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)
{
size_t s = end - data;
size_t s = static_cast<size_t>(end - data);
if (s < 4)
return false;
@ -197,8 +199,7 @@ void progress_parse(uint8_t*& ptr, uint8_t* end, size_t& sz)
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,
std::vector<uint8_t>& sei)
void hevc::extract_header_sei(uint8_t* data, size_t sz_data, std::vector<uint8_t>& header, std::vector<uint8_t>& sei)
{
uint8_t* ptr = 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:
sei.insert(sei.end(), ptr, ptr + nal_sz);
break;
default:
break;
}
}
}

View file

@ -28,42 +28,36 @@
#define P_HEVC_TIER "Codec.HEVC.Tier"
#define P_HEVC_LEVEL "Codec.HEVC.Level"
namespace obsffmpeg {
namespace codecs {
namespace hevc {
enum class profile {
MAIN,
MAIN10,
RANGE_EXTENDED,
UNKNOWN = -1,
};
namespace encoder::codec::hevc {
enum class profile {
MAIN,
MAIN10,
RANGE_EXTENDED,
UNKNOWN = -1,
};
enum class tier {
MAIN,
HIGH,
UNKNOWN = -1,
};
enum class tier {
MAIN,
HIGH,
UNKNOWN = -1,
};
enum class level {
L1_0 = 30,
L2_0 = 60,
L2_1 = 63,
L3_0 = 90,
L3_1 = 93,
L4_0 = 120,
L4_1 = 123,
L5_0 = 150,
L5_1 = 153,
L5_2 = 156,
L6_0 = 180,
L6_1 = 183,
L6_2 = 186,
UNKNOWN = -1,
};
enum class level {
L1_0 = 30,
L2_0 = 60,
L2_1 = 63,
L3_0 = 90,
L3_1 = 93,
L4_0 = 120,
L4_1 = 123,
L5_0 = 150,
L5_1 = 153,
L5_2 = 156,
L6_0 = 180,
L6_1 = 183,
L6_2 = 186,
UNKNOWN = -1,
};
void extract_header_sei(uint8_t* data, size_t sz_data, std::vector<uint8_t>& header,
std::vector<uint8_t>& sei);
} // namespace hevc
} // namespace codecs
} // namespace obsffmpeg
void extract_header_sei(uint8_t* data, size_t sz_data, std::vector<uint8_t>& header, std::vector<uint8_t>& sei);
} // namespace encoder::codec::hevc

File diff suppressed because it is too large Load diff

View file

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

View file

@ -23,6 +23,7 @@
#include <map>
#include <string>
#include <utility>
#include <vector>
#include "handler.hpp"
#include "plugin.hpp"
#include "utility.hpp"
@ -35,7 +36,9 @@ extern "C" {
#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>
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());
}
void obsffmpeg::ui::debug_handler::get_properties(obs_properties_t*, const AVCodec* codec, AVCodecContext* context,
bool)
void debug_handler::get_properties(obs_properties_t*, const AVCodec* codec, AVCodecContext* context, bool)
{
if (context)
return;
@ -76,28 +78,28 @@ void obsffmpeg::ui::debug_handler::get_properties(obs_properties_t*, const AVCod
return;
}
PLOG_INFO("Options for '%s':", codec->name);
LOG_INFO("Options for '%s':", codec->name);
std::pair<AVOptionType, std::string> opt_type_name[] = {
{AV_OPT_TYPE_FLAGS, "Flags"},
{AV_OPT_TYPE_INT, "Int"},
{AV_OPT_TYPE_INT64, "Int64"},
{AV_OPT_TYPE_DOUBLE, "Double"},
{AV_OPT_TYPE_FLOAT, "Float"},
{AV_OPT_TYPE_STRING, "String"},
{AV_OPT_TYPE_RATIONAL, "Rational"},
{AV_OPT_TYPE_BINARY, "Binary"},
{AV_OPT_TYPE_DICT, "Dictionary"},
{AV_OPT_TYPE_UINT64, "Unsigned Int64"},
{AV_OPT_TYPE_CONST, "Constant"},
{AV_OPT_TYPE_IMAGE_SIZE, "Image Size"},
{AV_OPT_TYPE_PIXEL_FMT, "Pixel Format"},
{AV_OPT_TYPE_SAMPLE_FMT, "Sample Format"},
{AV_OPT_TYPE_VIDEO_RATE, "Video Rate"},
{AV_OPT_TYPE_DURATION, "Duration"},
{AV_OPT_TYPE_COLOR, "Color"},
{AV_OPT_TYPE_CHANNEL_LAYOUT, "Layout"},
{AV_OPT_TYPE_BOOL, "Bool"},
{AV_OPT_TYPE_FLAGS, "Flags"},
{AV_OPT_TYPE_INT, "Int"},
{AV_OPT_TYPE_INT64, "Int64"},
{AV_OPT_TYPE_DOUBLE, "Double"},
{AV_OPT_TYPE_FLOAT, "Float"},
{AV_OPT_TYPE_STRING, "String"},
{AV_OPT_TYPE_RATIONAL, "Rational"},
{AV_OPT_TYPE_BINARY, "Binary"},
{AV_OPT_TYPE_DICT, "Dictionary"},
{AV_OPT_TYPE_UINT64, "Unsigned Int64"},
{AV_OPT_TYPE_CONST, "Constant"},
{AV_OPT_TYPE_IMAGE_SIZE, "Image Size"},
{AV_OPT_TYPE_PIXEL_FMT, "Pixel Format"},
{AV_OPT_TYPE_SAMPLE_FMT, "Sample Format"},
{AV_OPT_TYPE_VIDEO_RATE, "Video Rate"},
{AV_OPT_TYPE_DURATION, "Duration"},
{AV_OPT_TYPE_COLOR, "Color"},
{AV_OPT_TYPE_CHANNEL_LAYOUT, "Layout"},
{AV_OPT_TYPE_BOOL, "Bool"},
};
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->unit == nullptr) {
PLOG_INFO(" Constant '%s' and help text '%s' with unknown settings.", opt->name,
opt->help);
LOG_INFO(" Constant '%s' and help text '%s' with unknown settings.", opt->name, opt->help);
} else {
auto unit_type = unit_types.find(opt->unit);
if (unit_type == unit_types.end()) {
PLOG_INFO(" [%s] Flag '%s' and help text '%s' with value '%lld'.", opt->unit,
opt->name, opt->help, opt->default_val.i64);
LOG_INFO(" [%s] Flag '%s' and help text '%s' with value '%lld'.", opt->unit, opt->name, opt->help,
opt->default_val.i64);
} else {
std::string out;
switch (unit_type->second) {
@ -153,8 +154,8 @@ void obsffmpeg::ui::debug_handler::get_properties(obs_properties_t*, const AVCod
break;
}
PLOG_INFO(" [%s] Constant '%s' and help text '%s' with value '%s'.", opt->unit,
opt->name, opt->help, out.c_str());
LOG_INFO(" [%s] Constant '%s' and help text '%s' with value '%s'.", opt->unit, opt->name,
opt->help, out.c_str());
}
}
} else {
@ -198,13 +199,13 @@ void obsffmpeg::ui::debug_handler::get_properties(obs_properties_t*, const AVCod
}
}
PLOG_INFO(
" Option '%s'%s%s%s with help '%s' of type '%s' with default value '%s', minimum '%s' and maximum '%s'.",
opt->name, opt->unit ? " with unit (" : "", opt->unit ? opt->unit : "",
opt->unit ? ")" : "", opt->help, type_name.c_str(), out.c_str(), minimum.c_str(),
maximum.c_str());
LOG_INFO(
" Option '%s'%s%s%s with help '%s' of type '%s' with default value '%s', minimum '%s' and maximum "
"'%s'.",
opt->name, opt->unit ? " with unit (" : "", opt->unit ? opt->unit : "", opt->unit ? ")" : "", opt->help,
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*) {}

View file

@ -22,18 +22,15 @@
#pragma once
#include "handler.hpp"
namespace obsffmpeg {
namespace ui {
class debug_handler : public handler {
public:
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context,
bool hw_encode) override;
namespace encoder::ffmpeg::handler {
class debug_handler : public handler {
public:
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context,
bool hw_encode) override;
virtual void get_properties(obs_properties_t* props, const AVCodec* codec,
AVCodecContext* context, bool hw_encode) override;
virtual void get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context,
bool hw_encode) override;
virtual void update(obs_data_t* settings, const AVCodec* codec,
AVCodecContext* context) override;
};
} // namespace ui
} // namespace obsffmpeg
virtual void update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context) override;
};
} // namespace encoder::ffmpeg::handler

View file

@ -20,27 +20,29 @@
// SOFTWARE.
#include "handler.hpp"
#include "encoder.hpp"
#include "../ffmpeg-encoder.hpp"
void obsffmpeg::ui::handler::adjust_encoder_info(obsffmpeg::encoder_factory*, obsffmpeg::encoder_info*,
obsffmpeg::encoder_info*)
void encoder::ffmpeg::handler::handler::adjust_encoder_info(encoder::ffmpeg::ffmpeg_factory*, ffmpeg_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;
}
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*) {}

View file

@ -22,7 +22,7 @@
#pragma once
#include <string>
#include "hwapi/base.hpp"
#include "ffmpeg/hwapi/base.hpp"
extern "C" {
#include <obs.h>
@ -36,39 +36,37 @@ extern "C" {
#pragma warning(pop)
}
namespace obsffmpeg {
struct encoder_info;
class encoder_factory;
class encoder;
namespace encoder::ffmpeg {
struct ffmpeg_info;
class ffmpeg_factory;
class ffmpeg_instance;
namespace ui {
namespace handler {
class handler {
public /*factory*/:
virtual void adjust_encoder_info(obsffmpeg::encoder_factory* factory,
obsffmpeg::encoder_info* main,
obsffmpeg::encoder_info* fallback);
virtual void adjust_encoder_info(ffmpeg_factory* factory, ffmpeg_info* main, ffmpeg_info* fallback);
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context,
bool hw_encode);
bool hw_encode);
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,
AVCodecContext* context, bool hw_encode);
virtual void get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context,
bool hw_encode);
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);
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);
virtual void process_avpacket(AVPacket& packet, const AVCodec* codec, AVCodecContext* context);
};
} // namespace ui
} // namespace obsffmpeg
} // namespace handler
} // namespace encoder::ffmpeg

View file

@ -20,8 +20,8 @@
// SOFTWARE.
#include "nvenc_h264_handler.hpp"
#include "codecs/h264.hpp"
#include "encoder.hpp"
#include "../codecs/h264.hpp"
#include "../ffmpeg-encoder.hpp"
#include "ffmpeg/tools.hpp"
#include "nvenc_shared.hpp"
#include "plugin.hpp"
@ -36,52 +36,43 @@ extern "C" {
#pragma warning(pop)
}
using namespace obsffmpeg::codecs::h264;
using namespace encoder::ffmpeg::handler;
using namespace encoder::codec::h264;
std::map<profile, std::string> profiles{
{profile::BASELINE, "baseline"},
{profile::MAIN, "main"},
{profile::HIGH, "high"},
{profile::HIGH444_PREDICTIVE, "high444p"},
{profile::BASELINE, "baseline"},
{profile::MAIN, "main"},
{profile::HIGH, "high"},
{profile::HIGH444_PREDICTIVE, "high444p"},
};
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::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::L5_1, "5.1"}, {level::L5_2, "5.2"},
{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::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"},
};
INITIALIZER(nvenc_h264_handler_init)
{
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)
void nvenc_h264_handler::adjust_encoder_info(ffmpeg_factory*, ffmpeg_info* main, ffmpeg_info* fallback)
{
main->readable_name = "H.264/AVC NVidia NVENC (Hardware)";
fallback->readable_name = "H.264/AVC NVidia NVENC (Software)";
}
void obsffmpeg::ui::nvenc_h264_handler::get_defaults(obs_data_t* settings, const AVCodec* codec,
AVCodecContext* context, bool)
void nvenc_h264_handler::get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, bool)
{
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_LEVEL, static_cast<int64_t>(codecs::h264::level::UNKNOWN));
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>(level::UNKNOWN));
}
bool obsffmpeg::ui::nvenc_h264_handler::has_keyframe_support(obsffmpeg::encoder*)
bool nvenc_h264_handler::has_keyframe_support(ffmpeg_instance*)
{
return true;
}
void obsffmpeg::ui::nvenc_h264_handler::get_properties(obs_properties_t* props, const AVCodec* codec,
AVCodecContext* context, bool)
void nvenc_h264_handler::get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context, bool)
{
if (!context) {
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);
{
auto found =
profiles.find(static_cast<codecs::h264::profile>(obs_data_get_int(settings, P_H264_PROFILE)));
auto found = profiles.find(static_cast<profile>(obs_data_get_int(settings, P_H264_PROFILE)));
if (found != profiles.end()) {
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()) {
av_opt_set(context->priv_data, "level", found->second.c_str(), 0);
} 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);
}
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);
PLOG_INFO("[%s] H.265/HEVC:", codec->name);
ffmpeg::tools::print_av_option_string(context, "profile", " Profile", [](int64_t v) {
LOG_INFO("[%s] H.265/HEVC:", codec->name);
::ffmpeg::tools::print_av_option_string(context, "profile", " Profile", [](int64_t v) {
profile val = static_cast<profile>(v);
auto index = profiles.find(val);
if (index != profiles.end())
return index->second;
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);
auto index = levels.find(val);
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);
{
obs_properties_t* grp = props;
if (!obsffmpeg::are_property_groups_broken()) {
if (!util::are_property_groups_broken()) {
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),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_property_set_long_description(p, TRANSLATE(DESC(P_H264_PROFILE)));
obs_property_list_add_int(p, TRANSLATE(S_STATE_DEFAULT),
static_cast<int64_t>(codecs::h264::profile::UNKNOWN));
auto p = obs_properties_add_list(grp, P_H264_PROFILE, D_TRANSLATE(P_H264_PROFILE), OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_INT);
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(P_H264_PROFILE)));
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), static_cast<int64_t>(profile::UNKNOWN));
for (auto const kv : profiles) {
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),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_property_set_long_description(p, TRANSLATE(DESC(P_H264_LEVEL)));
obs_property_list_add_int(p, TRANSLATE(S_STATE_AUTOMATIC),
static_cast<int64_t>(codecs::h264::level::UNKNOWN));
auto p = obs_properties_add_list(grp, P_H264_LEVEL, D_TRANSLATE(P_H264_LEVEL), OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_INT);
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(P_H264_LEVEL)));
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_AUTOMATIC), static_cast<int64_t>(level::UNKNOWN));
for (auto const kv : levels) {
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);
}
void obsffmpeg::ui::nvenc_h264_handler::get_runtime_properties(obs_properties_t* props, const AVCodec* codec,
AVCodecContext* context)
void nvenc_h264_handler::get_runtime_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context)
{
nvenc::get_runtime_properties(props, codec, context);
}

View file

@ -30,37 +30,31 @@ extern "C" {
#pragma warning(pop)
}
namespace obsffmpeg {
namespace ui {
class nvenc_h264_handler : public handler {
public /*factory*/:
virtual void adjust_encoder_info(obsffmpeg::encoder_factory* factory,
obsffmpeg::encoder_info* main,
obsffmpeg::encoder_info* fallback);
namespace encoder::ffmpeg::handler {
class nvenc_h264_handler : public handler {
public /*factory*/:
virtual void adjust_encoder_info(ffmpeg_factory* factory, ffmpeg_info* main, ffmpeg_info* fallback);
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context,
bool hw_encode);
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, bool hw_encode);
public /*settings*/:
virtual bool has_keyframe_support(obsffmpeg::encoder* instance);
public /*settings*/:
virtual bool has_keyframe_support(ffmpeg_instance* instance);
virtual void get_properties(obs_properties_t* props, const AVCodec* codec,
AVCodecContext* context, bool hw_encode);
virtual void get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context,
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*/:
//virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
public /*instance*/:
//virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
private:
void get_encoder_properties(obs_properties_t* props, const AVCodec* codec);
private:
void get_encoder_properties(obs_properties_t* props, const AVCodec* codec);
void get_runtime_properties(obs_properties_t* props, const AVCodec* codec,
AVCodecContext* context);
};
} // namespace ui
} // namespace obsffmpeg
void get_runtime_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context);
};
} // namespace encoder::ffmpeg::handler

View file

@ -20,8 +20,8 @@
// SOFTWARE.
#include "nvenc_hevc_handler.hpp"
#include "codecs/hevc.hpp"
#include "encoder.hpp"
#include "../codecs/hevc.hpp"
#include "../ffmpeg-encoder.hpp"
#include "ffmpeg/tools.hpp"
#include "nvenc_shared.hpp"
#include "plugin.hpp"
@ -36,56 +36,47 @@ extern "C" {
#pragma warning(pop)
}
using namespace obsffmpeg::codecs::hevc;
using namespace encoder::ffmpeg::handler;
using namespace encoder::codec::hevc;
std::map<profile, std::string> profiles{
{profile::MAIN, "main"},
{profile::MAIN10, "main10"},
{profile::RANGE_EXTENDED, "rext"},
{profile::MAIN, "main"},
{profile::MAIN10, "main10"},
{profile::RANGE_EXTENDED, "rext"},
};
std::map<tier, std::string> tiers{
{tier::MAIN, "main"},
{tier::HIGH, "high"},
{tier::MAIN, "main"},
{tier::HIGH, "high"},
};
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::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::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::L6_0, "6.0"}, {level::L6_1, "6.1"}, {level::L6_2, "6.2"},
};
INITIALIZER(nvenc_hevc_handler_init)
{
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)
void nvenc_hevc_handler::adjust_encoder_info(ffmpeg_factory*, ffmpeg_info* main, ffmpeg_info* fallback)
{
main->readable_name = "H.265/HEVC Nvidia NVENC (Hardware)";
fallback->readable_name = "H.265/HEVC Nvidia NVENC (Software)";
}
void obsffmpeg::ui::nvenc_hevc_handler::get_defaults(obs_data_t* settings, const AVCodec* codec,
AVCodecContext* context, bool)
void nvenc_hevc_handler::get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, bool)
{
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_TIER, static_cast<int64_t>(codecs::hevc::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_PROFILE, static_cast<int64_t>(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>(level::UNKNOWN));
}
bool obsffmpeg::ui::nvenc_hevc_handler::has_keyframe_support(obsffmpeg::encoder*)
bool nvenc_hevc_handler::has_keyframe_support(ffmpeg_instance*)
{
return true;
}
void obsffmpeg::ui::nvenc_hevc_handler::get_properties(obs_properties_t* props, const AVCodec* codec,
AVCodecContext* context, bool)
void nvenc_hevc_handler::get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context, bool)
{
if (!context) {
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);
@ -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);
}
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);
PLOG_INFO("[%s] H.265/HEVC:", codec->name);
ffmpeg::tools::print_av_option_string(context, "profile", " Profile", [](int64_t v) {
LOG_INFO("[%s] H.265/HEVC:", codec->name);
::ffmpeg::tools::print_av_option_string(context, "profile", " Profile", [](int64_t v) {
profile val = static_cast<profile>(v);
auto index = profiles.find(val);
if (index != profiles.end())
return index->second;
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);
auto index = levels.find(val);
if (index != levels.end())
return index->second;
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);
auto index = tiers.find(val);
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);
{
obs_properties_t* grp = props;
if (!obsffmpeg::are_property_groups_broken()) {
if (!util::are_property_groups_broken()) {
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),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_property_set_long_description(p, TRANSLATE(DESC(P_HEVC_PROFILE)));
obs_property_list_add_int(p, TRANSLATE(S_STATE_DEFAULT),
static_cast<int64_t>(codecs::hevc::profile::UNKNOWN));
auto p = obs_properties_add_list(grp, P_HEVC_PROFILE, D_TRANSLATE(P_HEVC_PROFILE), OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_INT);
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(P_HEVC_PROFILE)));
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), static_cast<int64_t>(profile::UNKNOWN));
for (auto const kv : profiles) {
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,
OBS_COMBO_FORMAT_INT);
obs_property_set_long_description(p, TRANSLATE(DESC(P_HEVC_TIER)));
obs_property_list_add_int(p, TRANSLATE(S_STATE_DEFAULT),
static_cast<int64_t>(codecs::hevc::tier::UNKNOWN));
auto p = obs_properties_add_list(grp, P_HEVC_TIER, D_TRANSLATE(P_HEVC_TIER), OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_INT);
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(P_HEVC_TIER)));
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_DEFAULT), static_cast<int64_t>(tier::UNKNOWN));
for (auto const kv : tiers) {
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),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_property_set_long_description(p, TRANSLATE(DESC(P_HEVC_LEVEL)));
obs_property_list_add_int(p, TRANSLATE(S_STATE_AUTOMATIC),
static_cast<int64_t>(codecs::hevc::level::UNKNOWN));
auto p = obs_properties_add_list(grp, P_HEVC_LEVEL, D_TRANSLATE(P_HEVC_LEVEL), OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_INT);
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(P_HEVC_LEVEL)));
obs_property_list_add_int(p, D_TRANSLATE(S_STATE_AUTOMATIC), static_cast<int64_t>(level::UNKNOWN));
for (auto const kv : levels) {
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);
}
void obsffmpeg::ui::nvenc_hevc_handler::get_runtime_properties(obs_properties_t* props, const AVCodec* codec,
AVCodecContext* context)
void nvenc_hevc_handler::get_runtime_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context)
{
nvenc::get_runtime_properties(props, codec, context);
}

View file

@ -30,37 +30,31 @@ extern "C" {
#pragma warning(pop)
}
namespace obsffmpeg {
namespace ui {
class nvenc_hevc_handler : public handler {
public /*factory*/:
virtual void adjust_encoder_info(obsffmpeg::encoder_factory* factory,
obsffmpeg::encoder_info* main,
obsffmpeg::encoder_info* fallback);
namespace encoder::ffmpeg::handler {
class nvenc_hevc_handler : public handler {
public /*factory*/:
virtual void adjust_encoder_info(ffmpeg_factory* factory, ffmpeg_info* main, ffmpeg_info* fallback);
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context,
bool hw_encode);
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context, bool hw_encode);
public /*settings*/:
virtual bool has_keyframe_support(obsffmpeg::encoder* instance);
public /*settings*/:
virtual bool has_keyframe_support(ffmpeg_instance* instance);
virtual void get_properties(obs_properties_t* props, const AVCodec* codec,
AVCodecContext* context, bool hw_encode);
virtual void get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context,
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*/:
//virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
public /*instance*/:
//virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
private:
void get_encoder_properties(obs_properties_t* props, const AVCodec* codec);
private:
void get_encoder_properties(obs_properties_t* props, const AVCodec* codec);
void get_runtime_properties(obs_properties_t* props, const AVCodec* codec,
AVCodecContext* context);
};
} // namespace ui
} // namespace obsffmpeg
void get_runtime_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context);
};
} // namespace encoder::ffmpeg::handler

View file

@ -21,8 +21,8 @@
#include "nvenc_shared.hpp"
#include <algorithm>
#include "codecs/hevc.hpp"
#include "encoder.hpp"
#include "../codecs/hevc.hpp"
#include "../ffmpeg-encoder.hpp"
#include "ffmpeg/tools.hpp"
#include "plugin.hpp"
#include "strings.hpp"
@ -76,65 +76,67 @@ extern "C" {
#define ST_OTHER_WEIGHTED_PREDICTION ST_OTHER ".WeightedPrediction"
#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{
{preset::DEFAULT, ST_PRESET_(Default)},
{preset::SLOW, ST_PRESET_(Slow)},
{preset::MEDIUM, ST_PRESET_(Medium)},
{preset::FAST, ST_PRESET_(Fast)},
{preset::HIGH_PERFORMANCE, ST_PRESET_(HighPerformance)},
{preset::HIGH_QUALITY, ST_PRESET_(HighQuality)},
{preset::BLURAYDISC, ST_PRESET_(BluRayDisc)},
{preset::LOW_LATENCY, ST_PRESET_(LowLatency)},
{preset::LOW_LATENCY_HIGH_PERFORMANCE, ST_PRESET_(LowLatencyHighPerformance)},
{preset::LOW_LATENCY_HIGH_QUALITY, ST_PRESET_(LowLatencyHighQuality)},
{preset::LOSSLESS, ST_PRESET_(Lossless)},
{preset::LOSSLESS_HIGH_PERFORMANCE, ST_PRESET_(LosslessHighPerformance)},
std::map<nvenc::preset, std::string> nvenc::presets{
{nvenc::preset::DEFAULT, ST_PRESET_(Default)},
{nvenc::preset::SLOW, ST_PRESET_(Slow)},
{nvenc::preset::MEDIUM, ST_PRESET_(Medium)},
{nvenc::preset::FAST, ST_PRESET_(Fast)},
{nvenc::preset::HIGH_PERFORMANCE, ST_PRESET_(HighPerformance)},
{nvenc::preset::HIGH_QUALITY, ST_PRESET_(HighQuality)},
{nvenc::preset::BLURAYDISC, ST_PRESET_(BluRayDisc)},
{nvenc::preset::LOW_LATENCY, ST_PRESET_(LowLatency)},
{nvenc::preset::LOW_LATENCY_HIGH_PERFORMANCE, ST_PRESET_(LowLatencyHighPerformance)},
{nvenc::preset::LOW_LATENCY_HIGH_QUALITY, ST_PRESET_(LowLatencyHighQuality)},
{nvenc::preset::LOSSLESS, ST_PRESET_(Lossless)},
{nvenc::preset::LOSSLESS_HIGH_PERFORMANCE, ST_PRESET_(LosslessHighPerformance)},
};
std::map<preset, std::string> obsffmpeg::nvenc::preset_to_opt{
{preset::DEFAULT, "default"},
{preset::SLOW, "slow"},
{preset::MEDIUM, "medium"},
{preset::FAST, "fast"},
{preset::HIGH_PERFORMANCE, "hp"},
{preset::HIGH_QUALITY, "hq"},
{preset::BLURAYDISC, "bd"},
{preset::LOW_LATENCY, "ll"},
{preset::LOW_LATENCY_HIGH_PERFORMANCE, "llhp"},
{preset::LOW_LATENCY_HIGH_QUALITY, "llhq"},
{preset::LOSSLESS, "lossless"},
{preset::LOSSLESS_HIGH_PERFORMANCE, "losslesshp"},
std::map<nvenc::preset, std::string> nvenc::preset_to_opt{
{nvenc::preset::DEFAULT, "default"},
{nvenc::preset::SLOW, "slow"},
{nvenc::preset::MEDIUM, "medium"},
{nvenc::preset::FAST, "fast"},
{nvenc::preset::HIGH_PERFORMANCE, "hp"},
{nvenc::preset::HIGH_QUALITY, "hq"},
{nvenc::preset::BLURAYDISC, "bd"},
{nvenc::preset::LOW_LATENCY, "ll"},
{nvenc::preset::LOW_LATENCY_HIGH_PERFORMANCE, "llhp"},
{nvenc::preset::LOW_LATENCY_HIGH_QUALITY, "llhq"},
{nvenc::preset::LOSSLESS, "lossless"},
{nvenc::preset::LOSSLESS_HIGH_PERFORMANCE, "losslesshp"},
};
std::map<ratecontrolmode, std::string> obsffmpeg::nvenc::ratecontrolmodes{
{ratecontrolmode::CQP, ST_RATECONTROL_MODE_(CQP)},
{ratecontrolmode::VBR, ST_RATECONTROL_MODE_(VBR)},
{ratecontrolmode::VBR_HQ, ST_RATECONTROL_MODE_(VBR_HQ)},
{ratecontrolmode::CBR, ST_RATECONTROL_MODE_(CBR)},
{ratecontrolmode::CBR_HQ, ST_RATECONTROL_MODE_(CBR_HQ)},
{ratecontrolmode::CBR_LD_HQ, ST_RATECONTROL_MODE_(CBR_LD_HQ)},
std::map<nvenc::ratecontrolmode, std::string> nvenc::ratecontrolmodes{
{nvenc::ratecontrolmode::CQP, ST_RATECONTROL_MODE_(CQP)},
{nvenc::ratecontrolmode::VBR, ST_RATECONTROL_MODE_(VBR)},
{nvenc::ratecontrolmode::VBR_HQ, ST_RATECONTROL_MODE_(VBR_HQ)},
{nvenc::ratecontrolmode::CBR, ST_RATECONTROL_MODE_(CBR)},
{nvenc::ratecontrolmode::CBR_HQ, ST_RATECONTROL_MODE_(CBR_HQ)},
{nvenc::ratecontrolmode::CBR_LD_HQ, ST_RATECONTROL_MODE_(CBR_LD_HQ)},
};
std::map<ratecontrolmode, std::string> obsffmpeg::nvenc::ratecontrolmode_to_opt{
{ratecontrolmode::CQP, "constqp"}, {ratecontrolmode::VBR, "vbr"}, {ratecontrolmode::VBR_HQ, "vbr_hq"},
{ratecontrolmode::CBR, "cbr"}, {ratecontrolmode::CBR_HQ, "cbr_hq"}, {ratecontrolmode::CBR_LD_HQ, "cbr_ld_hq"},
std::map<nvenc::ratecontrolmode, std::string> nvenc::ratecontrolmode_to_opt{
{nvenc::ratecontrolmode::CQP, "constqp"}, {nvenc::ratecontrolmode::VBR, "vbr"},
{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{
{b_ref_mode::DISABLED, S_STATE_DISABLED},
{b_ref_mode::EACH, ST_OTHER_BFRAME_REFERENCEMODE ".Each"},
{b_ref_mode::MIDDLE, ST_OTHER_BFRAME_REFERENCEMODE ".Middle"},
std::map<nvenc::b_ref_mode, std::string> nvenc::b_ref_modes{
{nvenc::b_ref_mode::DISABLED, S_STATE_DISABLED},
{nvenc::b_ref_mode::EACH, ST_OTHER_BFRAME_REFERENCEMODE ".Each"},
{nvenc::b_ref_mode::MIDDLE, ST_OTHER_BFRAME_REFERENCEMODE ".Middle"},
};
std::map<b_ref_mode, std::string> obsffmpeg::nvenc::b_ref_mode_to_opt{
{b_ref_mode::DISABLED, "disabled"},
{b_ref_mode::EACH, "each"},
{b_ref_mode::MIDDLE, "middle"},
std::map<nvenc::b_ref_mode, std::string> nvenc::b_ref_mode_to_opt{
{nvenc::b_ref_mode::DISABLED, "disabled"},
{nvenc::b_ref_mode::EACH, "each"},
{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());
@ -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));
}
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_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);
}
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_max = false;
bool have_quality = false;
bool have_qp = 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) {
case ratecontrolmode::CQP:
case nvenc::ratecontrolmode::CQP:
have_qp = true;
break;
case ratecontrolmode::CBR:
case ratecontrolmode::CBR_HQ:
case ratecontrolmode::CBR_LD_HQ:
case nvenc::ratecontrolmode::INVALID:
case nvenc::ratecontrolmode::CBR:
case nvenc::ratecontrolmode::CBR_HQ:
case nvenc::ratecontrolmode::CBR_LD_HQ:
have_bitrate = true;
break;
case ratecontrolmode::VBR:
case ratecontrolmode::VBR_HQ:
case nvenc::ratecontrolmode::VBR:
case nvenc::ratecontrolmode::VBR_HQ:
have_bitrate = true;
have_bitrate_max = true;
have_quality = true;
@ -253,7 +254,7 @@ static bool modified_ratecontrol(obs_properties_t* props, obs_property_t*, obs_d
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);
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;
}
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;
obs_property_set_visible(obs_properties_get(props, ST_AQ_STRENGTH), spatial_aq);
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,
OBS_COMBO_FORMAT_INT);
obs_property_set_long_description(p, TRANSLATE(DESC(ST_PRESET)));
auto p = obs_properties_add_list(props, ST_PRESET, D_TRANSLATE(ST_PRESET), OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_INT);
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_PRESET)));
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
obs_properties_t* grp = props;
if (!obsffmpeg::are_property_groups_broken()) {
if (!util::are_property_groups_broken()) {
grp = obs_properties_create();
obs_properties_add_group(props, ST_RATECONTROL, TRANSLATE(ST_RATECONTROL), OBS_GROUP_NORMAL,
grp);
obs_properties_add_group(props, ST_RATECONTROL, D_TRANSLATE(ST_RATECONTROL), OBS_GROUP_NORMAL, grp);
}
{
auto p = obs_properties_add_list(grp, ST_RATECONTROL_MODE, TRANSLATE(ST_RATECONTROL_MODE),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_property_set_long_description(p, TRANSLATE(DESC(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_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_MODE)));
obs_property_set_modified_callback(p, modified_ratecontrol);
for (auto kv : ratecontrolmodes) {
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));
}
}
{
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_RATECONTROL_TWOPASS,
TRANSLATE(ST_RATECONTROL_TWOPASS));
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_TWOPASS)));
auto p =
util::obs_properties_add_tristate(grp, ST_RATECONTROL_TWOPASS, D_TRANSLATE(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,
TRANSLATE(ST_RATECONTROL_LOOKAHEAD), 0, 32, 1);
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_LOOKAHEAD)));
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_LOOKAHEAD, D_TRANSLATE(ST_RATECONTROL_LOOKAHEAD),
0, 32, 1);
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_LOOKAHEAD)));
obs_property_int_set_suffix(p, " frames");
}
{
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_RATECONTROL_ADAPTIVEI,
TRANSLATE(ST_RATECONTROL_ADAPTIVEI));
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_ADAPTIVEI)));
auto p =
util::obs_properties_add_tristate(grp, ST_RATECONTROL_ADAPTIVEI, D_TRANSLATE(ST_RATECONTROL_ADAPTIVEI));
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_ADAPTIVEI)));
}
if (strcmp(codec->name, "h264_nvenc") == 0) {
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_RATECONTROL_ADAPTIVEB,
TRANSLATE(ST_RATECONTROL_ADAPTIVEB));
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_ADAPTIVEB)));
auto p =
util::obs_properties_add_tristate(grp, ST_RATECONTROL_ADAPTIVEB, D_TRANSLATE(ST_RATECONTROL_ADAPTIVEB));
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_ADAPTIVEB)));
}
}
{
obs_properties_t* grp = props;
if (!obsffmpeg::are_property_groups_broken()) {
if (!util::are_property_groups_broken()) {
grp = obs_properties_create();
obs_properties_add_group(props, ST_RATECONTROL_BITRATE, TRANSLATE(ST_RATECONTROL_BITRATE),
OBS_GROUP_NORMAL, grp);
obs_properties_add_group(props, ST_RATECONTROL_BITRATE, D_TRANSLATE(ST_RATECONTROL_BITRATE),
OBS_GROUP_NORMAL, grp);
}
{
auto p = obs_properties_add_int(grp, ST_RATECONTROL_BITRATE_TARGET,
TRANSLATE(ST_RATECONTROL_BITRATE_TARGET), 1,
std::numeric_limits<int32_t>::max(), 1);
obs_property_set_long_description(p, TRANSLATE(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)));
auto p =
obs_properties_add_int(grp, ST_RATECONTROL_BITRATE_TARGET, D_TRANSLATE(ST_RATECONTROL_BITRATE_TARGET),
1, std::numeric_limits<int32_t>::max(), 1);
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, S_RATECONTROL_BUFFERSIZE, TRANSLATE(S_RATECONTROL_BUFFERSIZE),
0, std::numeric_limits<int32_t>::max(), 1);
obs_property_set_long_description(p, TRANSLATE(DESC(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);
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_properties_t* grp = props;
if (!obsffmpeg::are_property_groups_broken()) {
if (!util::are_property_groups_broken()) {
grp = obs_properties_create();
auto p = obs_properties_add_group(props, ST_RATECONTROL_QUALITY,
TRANSLATE(ST_RATECONTROL_QUALITY), OBS_GROUP_CHECKABLE, grp);
auto p = obs_properties_add_group(props, ST_RATECONTROL_QUALITY, D_TRANSLATE(ST_RATECONTROL_QUALITY),
OBS_GROUP_CHECKABLE, grp);
obs_property_set_modified_callback(p, modified_quality);
} else {
auto p =
obs_properties_add_bool(props, ST_RATECONTROL_QUALITY, TRANSLATE(ST_RATECONTROL_QUALITY));
auto p = obs_properties_add_bool(props, ST_RATECONTROL_QUALITY, D_TRANSLATE(ST_RATECONTROL_QUALITY));
obs_property_set_modified_callback(p, modified_quality);
}
{
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_QUALITY_MINIMUM,
TRANSLATE(ST_RATECONTROL_QUALITY_MINIMUM), 0, 51, 1);
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_QUALITY_MINIMUM)));
D_TRANSLATE(ST_RATECONTROL_QUALITY_MINIMUM), 0, 51, 1);
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,
TRANSLATE(ST_RATECONTROL_QUALITY_MAXIMUM), -1, 51, 1);
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_QUALITY_MAXIMUM)));
D_TRANSLATE(ST_RATECONTROL_QUALITY_MAXIMUM), -1, 51, 1);
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,
TRANSLATE(ST_RATECONTROL_QUALITY_TARGET), 0, 100, 0.01);
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_QUALITY_TARGET)));
D_TRANSLATE(ST_RATECONTROL_QUALITY_TARGET), 0, 100, 0.01);
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_QUALITY_TARGET)));
}
{
obs_properties_t* grp = props;
if (!obsffmpeg::are_property_groups_broken()) {
if (!util::are_property_groups_broken()) {
grp = obs_properties_create();
auto p = obs_properties_add_group(props, ST_RATECONTROL_QP, TRANSLATE(ST_RATECONTROL_QP),
OBS_GROUP_CHECKABLE, grp);
auto p = obs_properties_add_group(props, ST_RATECONTROL_QP, D_TRANSLATE(ST_RATECONTROL_QP),
OBS_GROUP_CHECKABLE, grp);
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),
0, 51, 1);
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_QP_I)));
auto p =
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, D_TRANSLATE(D_DESC(ST_RATECONTROL_QP_I)));
}
{
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_QP_I_INITIAL,
TRANSLATE(ST_RATECONTROL_QP_I_INITIAL), -1, 51, 1);
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_QP_I_INITIAL)));
D_TRANSLATE(ST_RATECONTROL_QP_I_INITIAL), -1, 51, 1);
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),
0, 51, 1);
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_QP_P)));
auto p =
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, D_TRANSLATE(D_DESC(ST_RATECONTROL_QP_P)));
}
{
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_QP_P_INITIAL,
TRANSLATE(ST_RATECONTROL_QP_P_INITIAL), -1, 51, 1);
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_QP_P_INITIAL)));
D_TRANSLATE(ST_RATECONTROL_QP_P_INITIAL), -1, 51, 1);
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),
0, 51, 1);
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_QP_B)));
auto p =
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, D_TRANSLATE(D_DESC(ST_RATECONTROL_QP_B)));
}
{
auto p = obs_properties_add_int_slider(grp, ST_RATECONTROL_QP_B_INITIAL,
TRANSLATE(ST_RATECONTROL_QP_B_INITIAL), -1, 51, 1);
obs_property_set_long_description(p, TRANSLATE(DESC(ST_RATECONTROL_QP_B_INITIAL)));
D_TRANSLATE(ST_RATECONTROL_QP_B_INITIAL), -1, 51, 1);
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_RATECONTROL_QP_B_INITIAL)));
}
}
{
obs_properties_t* grp = props;
if (!obsffmpeg::are_property_groups_broken()) {
if (!util::are_property_groups_broken()) {
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));
obs_property_set_long_description(p, TRANSLATE(DESC(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, D_TRANSLATE(D_DESC(ST_AQ_SPATIAL)));
obs_property_set_modified_callback(p, modified_aq);
}
{
auto p =
obs_properties_add_int_slider(grp, ST_AQ_STRENGTH, TRANSLATE(ST_AQ_STRENGTH), 1, 15, 1);
obs_property_set_long_description(p, TRANSLATE(DESC(ST_AQ_STRENGTH)));
auto p = obs_properties_add_int_slider(grp, ST_AQ_STRENGTH, D_TRANSLATE(ST_AQ_STRENGTH), 1, 15, 1);
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_AQ_STRENGTH)));
}
{
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_AQ_TEMPORAL, TRANSLATE(ST_AQ_TEMPORAL));
obs_property_set_long_description(p, TRANSLATE(DESC(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, D_TRANSLATE(D_DESC(ST_AQ_TEMPORAL)));
}
}
{
obs_properties_t* grp = props;
if (!obsffmpeg::are_property_groups_broken()) {
if (!util::are_property_groups_broken()) {
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 =
obs_properties_add_int_slider(grp, ST_OTHER_BFRAMES, TRANSLATE(ST_OTHER_BFRAMES), 0, 4, 1);
obs_property_set_long_description(p, TRANSLATE(DESC(ST_OTHER_BFRAMES)));
auto p = obs_properties_add_int_slider(grp, ST_OTHER_BFRAMES, D_TRANSLATE(ST_OTHER_BFRAMES), 0, 4, 1);
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_OTHER_BFRAMES)));
obs_property_int_set_suffix(p, " frames");
}
{
auto p = obs_properties_add_list(grp, ST_OTHER_BFRAME_REFERENCEMODE,
TRANSLATE(ST_OTHER_BFRAME_REFERENCEMODE), OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_INT);
obs_property_set_long_description(p, TRANSLATE(DESC(ST_OTHER_BFRAME_REFERENCEMODE)));
auto p =
obs_properties_add_list(grp, ST_OTHER_BFRAME_REFERENCEMODE, D_TRANSLATE(ST_OTHER_BFRAME_REFERENCEMODE),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_OTHER_BFRAME_REFERENCEMODE)));
for (auto kv : b_ref_modes) {
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));
}
}
{
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_OTHER_ZEROLATENCY,
TRANSLATE(ST_OTHER_ZEROLATENCY));
obs_property_set_long_description(p, TRANSLATE(DESC(ST_OTHER_ZEROLATENCY)));
auto p = util::obs_properties_add_tristate(grp, ST_OTHER_ZEROLATENCY, D_TRANSLATE(ST_OTHER_ZEROLATENCY));
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_OTHER_ZEROLATENCY)));
}
{
auto p = obsffmpeg::obs_properties_add_tristate(grp, ST_OTHER_WEIGHTED_PREDICTION,
TRANSLATE(ST_OTHER_WEIGHTED_PREDICTION));
obs_property_set_long_description(p, TRANSLATE(DESC(ST_OTHER_WEIGHTED_PREDICTION)));
auto p = util::obs_properties_add_tristate(grp, ST_OTHER_WEIGHTED_PREDICTION,
D_TRANSLATE(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,
TRANSLATE(ST_OTHER_NONREFERENCE_PFRAMES));
obs_property_set_long_description(p, TRANSLATE(DESC(ST_OTHER_NONREFERENCE_PFRAMES)));
auto p = util::obs_properties_add_tristate(grp, ST_OTHER_NONREFERENCE_PFRAMES,
D_TRANSLATE(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_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);
}
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));
@ -552,8 +545,8 @@ void obsffmpeg::nvenc::update(obs_data_t* settings, const AVCodec* codec, AVCode
bool have_qp_init = false;
ratecontrolmode rc = static_cast<ratecontrolmode>(obs_data_get_int(settings, ST_RATECONTROL_MODE));
auto rcopt = nvenc::ratecontrolmode_to_opt.find(rc);
if (rcopt != nvenc::ratecontrolmode_to_opt.end()) {
auto rcopt = ratecontrolmode_to_opt.find(rc);
if (rcopt != ratecontrolmode_to_opt.end()) {
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:
have_qp = true;
break;
case ratecontrolmode::INVALID:
case ratecontrolmode::CBR:
case ratecontrolmode::CBR_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);
if (la > 0) {
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);
}
if (strcmp(codec->name, "h264_nvenc")) {
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);
}
}
}
if (have_bitrate) {
context->bit_rate =
static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_BITRATE_TARGET) * 1000);
context->bit_rate = static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_BITRATE_TARGET) * 1000);
// Support for Replay Buffer
obs_data_set_int(settings, "bitrate",
obs_data_get_int(settings, ST_RATECONTROL_BITRATE_TARGET));
obs_data_set_int(settings, "bitrate", obs_data_get_int(settings, ST_RATECONTROL_BITRATE_TARGET));
}
if (have_bitrate_max)
context->rc_max_rate =
static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_BITRATE_MAXIMUM) * 1000);
context->rc_max_rate = static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_BITRATE_MAXIMUM) * 1000);
if (have_bitrate || have_bitrate_max)
context->rc_buffer_size =
static_cast<int>(obs_data_get_int(settings, S_RATECONTROL_BUFFERSIZE) * 1000);
context->rc_buffer_size = static_cast<int>(obs_data_get_int(settings, S_RATECONTROL_BUFFERSIZE) * 1000);
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));
context->qmin = qmin;
if (qmin >= 0) {
context->qmax =
static_cast<int>(obs_data_get_int(settings, ST_RATECONTROL_QUALITY_MAXIMUM));
context->qmax = 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) {
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",
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",
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) {
av_opt_set_int(context->priv_data, "init_qpI",
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_qpB",
obs_data_get_int(settings, ST_RATECONTROL_QP_B_INITIAL), 0);
av_opt_set_int(context->priv_data, "init_qpI", 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_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);
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);
if (!is_tristate_default(taq))
if (!util::is_tristate_default(taq))
av_opt_set_int(context->priv_data, "temporal-aq", taq, 0);
} else {
if (!is_tristate_default(saq))
if (!util::is_tristate_default(saq))
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);
}
if (is_tristate_enabled(saq))
if (util::is_tristate_enabled(saq))
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
@ -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));
if (!is_tristate_default(zl))
if (!util::is_tristate_default(zl))
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);
if ((context->max_b_frames != 0) && is_tristate_enabled(wp)) {
PLOG_WARNING("[%s] Weighted Prediction disabled because of B-Frames being used.", codec->name);
if ((context->max_b_frames != 0) && util::is_tristate_enabled(wp)) {
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);
} else if (!is_tristate_default(wp)) {
} else if (!util::is_tristate_default(wp)) {
av_opt_set_int(context->priv_data, "weighted_pred", wp, 0);
}
{
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()) {
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);
ffmpeg::tools::print_av_option_string(context, "preset", " Preset", [](int64_t v) {
LOG_INFO("[%s] Nvidia NVENC:", codec->name);
tools::print_av_option_string(context, "preset", " Preset", [](int64_t v) {
preset val = static_cast<preset>(v);
std::string name = "<Unknown>";
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;
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);
std::string name = "<Unknown>";
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;
return name;
});
ffmpeg::tools::print_av_option_bool(context, "2pass", " Two Pass");
ffmpeg::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, "2pass", " Two Pass");
tools::print_av_option_int(context, "rc-lookahead", " Look-Ahead", "Frames");
tools::print_av_option_bool(context, "no-scenecut", " Adaptive I-Frames");
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);
ffmpeg::tools::print_av_option_int(context, "bitrate", " Target", "bits/sec");
ffmpeg::tools::print_av_option_int(context, "rc_max_rate", " Maximum", "bits/sec");
ffmpeg::tools::print_av_option_int(context, "rc_buffer_size", " Buffer", "bits");
PLOG_INFO("[%s] Quality:", codec->name);
ffmpeg::tools::print_av_option_int(context, "qmin", " Minimum", "");
ffmpeg::tools::print_av_option_int(context, "cq", " Target", "");
ffmpeg::tools::print_av_option_int(context, "qmax", " Maximum", "");
PLOG_INFO("[%s] Quantization Parameters:", codec->name);
ffmpeg::tools::print_av_option_int(context, "init_qpI", " I-Frame", "");
ffmpeg::tools::print_av_option_int(context, "init_qpP", " P-Frame", "");
ffmpeg::tools::print_av_option_int(context, "init_qpB", " B-Frame", "");
LOG_INFO("[%s] Bitrate:", codec->name);
tools::print_av_option_int(context, "bitrate", " Target", "bits/sec");
tools::print_av_option_int(context, "rc_max_rate", " Maximum", "bits/sec");
tools::print_av_option_int(context, "rc_buffer_size", " Buffer", "bits");
LOG_INFO("[%s] Quality:", codec->name);
tools::print_av_option_int(context, "qmin", " Minimum", "");
tools::print_av_option_int(context, "cq", " Target", "");
tools::print_av_option_int(context, "qmax", " Maximum", "");
LOG_INFO("[%s] Quantization Parameters:", codec->name);
tools::print_av_option_int(context, "init_qpI", " I-Frame", "");
tools::print_av_option_int(context, "init_qpP", " P-Frame", "");
tools::print_av_option_int(context, "init_qpB", " B-Frame", "");
ffmpeg::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_int(context, "max_b_frames", " B-Frames", "Frames");
tools::print_av_option_string(context, "b_ref_mode", " Reference Mode", [](int64_t v) {
b_ref_mode val = static_cast<b_ref_mode>(v);
std::string name = "<Unknown>";
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;
});
PLOG_INFO("[%s] Adaptive Quantization:", codec->name);
LOG_INFO("[%s] Adaptive Quantization:", codec->name);
if (strcmp(codec->name, "h264_nvenc") == 0) {
ffmpeg::tools::print_av_option_bool(context, "spatial-aq", " Spatial AQ");
ffmpeg::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, "spatial-aq", " Spatial AQ");
tools::print_av_option_int(context, "aq-strength", " Strength", "");
tools::print_av_option_bool(context, "temporal-aq", " Temporal AQ");
} else {
ffmpeg::tools::print_av_option_bool(context, "spatial_aq", " Spatial AQ");
ffmpeg::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, "spatial_aq", " Spatial AQ");
tools::print_av_option_int(context, "aq-strength", " Strength", "");
tools::print_av_option_bool(context, "temporal_aq", " Temporal AQ");
}
PLOG_INFO("[%s] Other:", codec->name);
ffmpeg::tools::print_av_option_bool(context, "zerolatency", " Zero Latency");
ffmpeg::tools::print_av_option_bool(context, "weighted_pred", " Weighted Prediction");
ffmpeg::tools::print_av_option_bool(context, "nonref_p", " Non-reference P-Frames");
ffmpeg::tools::print_av_option_bool(context, "strict_gop", " Strict GOP");
ffmpeg::tools::print_av_option_bool(context, "aud", " Access Unit Delimiters");
ffmpeg::tools::print_av_option_bool(context, "bluray-compat", " Bluray Compatibility");
LOG_INFO("[%s] Other:", codec->name);
tools::print_av_option_bool(context, "zerolatency", " Zero Latency");
tools::print_av_option_bool(context, "weighted_pred", " Weighted Prediction");
tools::print_av_option_bool(context, "nonref_p", " Non-reference P-Frames");
tools::print_av_option_bool(context, "strict_gop", " Strict GOP");
tools::print_av_option_bool(context, "aud", " Access Unit Delimiters");
tools::print_av_option_bool(context, "bluray-compat", " Bluray Compatibility");
if (strcmp(codec->name, "h264_nvenc") == 0)
ffmpeg::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_bool(context, "a53cc", " A53 Closed Captions");
tools::print_av_option_int(context, "dpb_size", " DPB Size", "");
}

View file

@ -21,6 +21,8 @@
#pragma once
#include <map>
#include <string>
#include "handler.hpp"
#include "utility.hpp"
extern "C" {
@ -31,70 +33,68 @@ extern "C" {
#pragma warning(pop)
}
namespace obsffmpeg {
class encoder;
using namespace encoder::ffmpeg;
namespace nvenc {
enum class preset : int64_t {
DEFAULT,
SLOW,
MEDIUM,
FAST,
HIGH_PERFORMANCE,
HIGH_QUALITY,
BLURAYDISC,
LOW_LATENCY,
LOW_LATENCY_HIGH_PERFORMANCE,
LOW_LATENCY_HIGH_QUALITY,
LOSSLESS,
LOSSLESS_HIGH_PERFORMANCE,
// Append things before this.
INVALID = -1,
};
namespace encoder::ffmpeg::handler::nvenc {
enum class preset : int64_t {
DEFAULT,
SLOW,
MEDIUM,
FAST,
HIGH_PERFORMANCE,
HIGH_QUALITY,
BLURAYDISC,
LOW_LATENCY,
LOW_LATENCY_HIGH_PERFORMANCE,
LOW_LATENCY_HIGH_QUALITY,
LOSSLESS,
LOSSLESS_HIGH_PERFORMANCE,
// Append things before this.
INVALID = -1,
};
enum class ratecontrolmode : int64_t {
CQP,
VBR,
VBR_HQ,
CBR,
CBR_HQ,
CBR_LD_HQ,
// Append things before this.
INVALID = -1,
};
enum class ratecontrolmode : int64_t {
CQP,
VBR,
VBR_HQ,
CBR,
CBR_HQ,
CBR_LD_HQ,
// Append things before this.
INVALID = -1,
};
enum class b_ref_mode : int64_t {
DISABLED,
EACH,
MIDDLE,
// Append things before this.
INVALID = -1,
};
enum class b_ref_mode : int64_t {
DISABLED,
EACH,
MIDDLE,
// Append things before this.
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);
} // namespace nvenc
} // namespace obsffmpeg
void log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context);
} // namespace encoder::ffmpeg::handler::nvenc

View file

@ -20,7 +20,7 @@
// SOFTWARE.
#include "prores_aw_handler.hpp"
#include "codecs/prores.hpp"
#include "../codecs/prores.hpp"
#include "ffmpeg/tools.hpp"
#include "plugin.hpp"
#include "utility.hpp"
@ -29,15 +29,10 @@ extern "C" {
#include <obs-module.h>
}
INITIALIZER(prores_aw_handler_init)
{
obsffmpeg::initializers.push_back([]() {
obsffmpeg::register_codec_handler("prores_aw", std::make_shared<obsffmpeg::ui::prores_aw_handler>());
});
};
using namespace encoder::ffmpeg::handler;
void obsffmpeg::ui::prores_aw_handler::override_colorformat(AVPixelFormat& target_format, obs_data_t* settings,
const AVCodec* codec, AVCodecContext*)
void prores_aw_handler::override_colorformat(AVPixelFormat& target_format, obs_data_t* settings, const AVCodec* codec,
AVCodecContext*)
{
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 = {
{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 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);
}
@ -70,29 +65,28 @@ inline const char* profile_to_name(const AVProfile* ptr)
{
switch (ptr->profile) {
case 0:
return TRANSLATE(P_PRORES_PROFILE_APCO);
return D_TRANSLATE(P_PRORES_PROFILE_APCO);
case 1:
return TRANSLATE(P_PRORES_PROFILE_APCS);
return D_TRANSLATE(P_PRORES_PROFILE_APCS);
case 2:
return TRANSLATE(P_PRORES_PROFILE_APCN);
return D_TRANSLATE(P_PRORES_PROFILE_APCN);
case 3:
return TRANSLATE(P_PRORES_PROFILE_APCH);
return D_TRANSLATE(P_PRORES_PROFILE_APCH);
case 4:
return TRANSLATE(P_PRORES_PROFILE_AP4H);
return D_TRANSLATE(P_PRORES_PROFILE_AP4H);
case 5:
return TRANSLATE(P_PRORES_PROFILE_AP4X);
return D_TRANSLATE(P_PRORES_PROFILE_AP4X);
default:
return ptr->name;
}
}
void obsffmpeg::ui::prores_aw_handler::get_properties(obs_properties_t* props, const AVCodec* codec,
AVCodecContext* context, bool)
void prores_aw_handler::get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context, bool)
{
if (!context) {
auto p = obs_properties_add_list(props, P_PRORES_PROFILE, TRANSLATE(P_PRORES_PROFILE),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_property_set_long_description(p, TRANSLATE(DESC(P_PRORES_PROFILE)));
auto p = obs_properties_add_list(props, P_PRORES_PROFILE, D_TRANSLATE(P_PRORES_PROFILE), OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_INT);
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(P_PRORES_PROFILE)));
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));
}
@ -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));
}
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);
ffmpeg::tools::print_av_option_string(context, "profile", " Profile", [&codec](int64_t v) {
LOG_INFO("[%s] Apple ProRes:", codec->name);
::ffmpeg::tools::print_av_option_string(context, "profile", " Profile", [&codec](int64_t v) {
int val = static_cast<int>(v);
for (auto ptr = codec->profiles; (ptr->profile != FF_PROFILE_UNKNOWN) && (ptr != nullptr); ptr++) {
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:
// When ProRes content is stored in Matroska, FFmpeg strips the size

View file

@ -30,27 +30,22 @@ extern "C" {
#pragma warning(pop)
}
namespace obsffmpeg {
namespace ui {
class prores_aw_handler : public handler {
public:
virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings,
const AVCodec* codec, AVCodecContext* context) override;
namespace encoder::ffmpeg::handler {
class prores_aw_handler : public handler {
public:
virtual void override_colorformat(AVPixelFormat& target_format, obs_data_t* settings, const AVCodec* codec,
AVCodecContext* context) override;
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context,
bool hw_encode) override;
virtual void get_defaults(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context,
bool hw_encode) override;
virtual void get_properties(obs_properties_t* props, const AVCodec* codec,
AVCodecContext* context, bool hw_encode) override;
virtual void get_properties(obs_properties_t* props, const AVCodec* codec, AVCodecContext* context,
bool hw_encode) override;
virtual void update(obs_data_t* settings, const AVCodec* codec,
AVCodecContext* context) override;
virtual void update(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context) override;
virtual void log_options(obs_data_t* settings, const AVCodec* codec,
AVCodecContext* context) override;
virtual void log_options(obs_data_t* settings, const AVCodec* codec, AVCodecContext* context) override;
virtual void process_avpacket(AVPacket& packet, const AVCodec* codec,
AVCodecContext* context) override;
};
} // namespace ui
} // namespace obsffmpeg
virtual void process_avpacket(AVPacket& packet, const AVCodec* codec, AVCodecContext* context) override;
};
} // namespace encoder::ffmpeg::handler

View file

@ -22,98 +22,100 @@
#include "avframe-queue.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) {
av_frame_unref(frame);
av_frame_free(&frame);
});
frame->width = this->resolution.first;
frame->height = this->resolution.second;
frame->format = this->format;
frame->width = this->_resolution.first;
frame->height = this->_resolution.second;
frame->format = this->_format;
int res = av_frame_get_buffer(frame.get(), 32);
if (res < 0) {
throw std::exception(ffmpeg::tools::get_error_description(res));
throw std::exception(tools::get_error_description(res));
}
return frame;
}
ffmpeg::avframe_queue::avframe_queue() {}
avframe_queue::avframe_queue() {}
ffmpeg::avframe_queue::~avframe_queue()
avframe_queue::~avframe_queue()
{
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.second = height;
this->_resolution.first = width;
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;
height = this->resolution.second;
width = this->_resolution.first;
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++) {
push(create_frame());
}
}
void ffmpeg::avframe_queue::clear()
void avframe_queue::clear()
{
std::unique_lock<std::mutex> ulock(this->lock);
frames.clear();
std::unique_lock<std::mutex> ulock(this->_lock);
_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);
frames.push_back(frame);
std::unique_lock<std::mutex> ulock(this->_lock);
_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;
while (ret == nullptr) {
if (frames.size() == 0) {
if (_frames.size() == 0) {
ret = create_frame();
} else {
ret = frames.front();
ret = _frames.front();
if (ret == nullptr) {
ret = create_frame();
} else {
frames.pop_front();
if ((static_cast<uint32_t>(ret->width) != this->resolution.first)
|| (static_cast<uint32_t>(ret->height) != this->resolution.second)
|| (ret->format != this->format)) {
_frames.pop_front();
if ((static_cast<uint32_t>(ret->width) != this->_resolution.first)
|| (static_cast<uint32_t>(ret->height) != this->_resolution.second)
|| (ret->format != this->_format)) {
ret = nullptr;
}
}
@ -122,26 +124,26 @@ std::shared_ptr<AVFrame> ffmpeg::avframe_queue::pop()
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);
if (frames.size() == 0) {
std::unique_lock<std::mutex> ulock(this->_lock);
if (_frames.size() == 0) {
return nullptr;
}
std::shared_ptr<AVFrame> ret = frames.front();
std::shared_ptr<AVFrame> ret = _frames.front();
if (ret == nullptr) {
return nullptr;
}
frames.pop_front();
_frames.pop_front();
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();
}

View file

@ -32,11 +32,11 @@ extern "C" {
namespace ffmpeg {
class avframe_queue {
std::deque<std::shared_ptr<AVFrame>> frames;
std::mutex lock;
std::deque<std::shared_ptr<AVFrame>> _frames;
std::mutex _lock;
std::pair<uint32_t, uint32_t> resolution;
AVPixelFormat format = AV_PIX_FMT_NONE;
std::pair<uint32_t, uint32_t> _resolution;
AVPixelFormat _format = AV_PIX_FMT_NONE;
std::shared_ptr<AVFrame> create_frame();

View file

@ -35,36 +35,31 @@ extern "C" {
#pragma warning(pop)
}
namespace obsffmpeg {
namespace hwapi {
struct device {
std::pair<int64_t, int64_t> id;
std::string name;
};
namespace ffmpeg::hwapi {
struct device {
std::pair<int64_t, int64_t> id;
std::string name;
};
class instance;
class instance {
public:
virtual AVBufferRef* create_device_context() = 0;
class base {
public:
virtual std::list<obsffmpeg::hwapi::device> enumerate_adapters() = 0;
virtual std::shared_ptr<AVFrame> allocate_frame(AVBufferRef* frames) = 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 {
public:
virtual AVBufferRef* create_device_context() = 0;
class base {
public:
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,
uint64_t* next_lock_key, std::shared_ptr<AVFrame> frame) = 0;
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
virtual std::shared_ptr<hwapi::instance> create_from_obs() = 0;
};
} // namespace ffmpeg::hwapi

View file

@ -19,6 +19,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifdef WIN32
#include "d3d11.hpp"
#include <sstream>
#include <vector>
@ -26,14 +28,20 @@
extern "C" {
#pragma warning(push)
#pragma warning(disable : 4191)
#pragma warning(disable : 4242)
#pragma warning(disable : 4244)
#pragma warning(disable : 4365)
#pragma warning(disable : 4986)
#include <graphics/graphics.h>
#include <libavutil/hwcontext_d3d11va.h>
#include <obs.h>
#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");
if (!_dxgi_module)
@ -43,10 +51,12 @@ obsffmpeg::hwapi::d3d11::d3d11() : _dxgi_module(0), _d3d11_module(0)
if (!_d3d11_module)
throw std::runtime_error("Unable to load D3D11");
_CreateDXGIFactory = reinterpret_cast<CreateDXGIFactory_t>(GetProcAddress(_dxgi_module, "CreateDXGIFactory"));
_CreateDXGIFactory1 =
reinterpret_cast<CreateDXGIFactory1_t>(GetProcAddress(_dxgi_module, "CreateDXGIFactory1"));
_D3D11CreateDevice = reinterpret_cast<D3D11CreateDevice_t>(GetProcAddress(_d3d11_module, "D3D11CreateDevice"));
#pragma warning(push)
#pragma warning(disable : 4191)
_CreateDXGIFactory = reinterpret_cast<CreateDXGIFactory_t>(GetProcAddress(_dxgi_module, "CreateDXGIFactory"));
_CreateDXGIFactory1 = reinterpret_cast<CreateDXGIFactory1_t>(GetProcAddress(_dxgi_module, "CreateDXGIFactory1"));
_D3D11CreateDevice = reinterpret_cast<D3D11CreateDevice_t>(GetProcAddress(_d3d11_module, "D3D11CreateDevice"));
#pragma warning(pop)
if (!_CreateDXGIFactory && !_CreateDXGIFactory1)
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(_d3d11_module);
}
std::list<obsffmpeg::hwapi::device> obsffmpeg::hwapi::d3d11::enumerate_adapters()
std::list<device> d3d11::enumerate_adapters()
{
std::list<device> adapters;
@ -79,8 +89,8 @@ std::list<obsffmpeg::hwapi::device> obsffmpeg::hwapi::d3d11::enumerate_adapters(
dxgi_adapter->GetDesc1(&desc);
std::vector<char> buf(1024);
size_t len = snprintf(buf.data(), buf.size(), "%ls (VEN_%04x/DEV_%04x/SUB_%04x/REV_%04x)",
desc.Description, desc.VendorId, desc.DeviceId, desc.SubSysId, desc.Revision);
size_t len = snprintf(buf.data(), buf.size(), "%ls (VEN_%04x/DEV_%04x/SUB_%04x/REV_%04x)", desc.Description,
desc.VendorId, desc.DeviceId, desc.SubSysId, desc.Revision);
device dev;
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);
}
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;
ATL::CComPtr<ID3D11Device> device;
@ -115,27 +125,27 @@ std::shared_ptr<obsffmpeg::hwapi::instance> obsffmpeg::hwapi::d3d11::create(obsf
// Create a D3D11 Device
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,
D3D_FEATURE_LEVEL_11_1};
D3D_FEATURE_LEVEL_11_1};
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,
&context))) {
static_cast<UINT>(feature_levels.size()), D3D11_SDK_VERSION, &device, NULL,
&context))) {
throw std::runtime_error("Failed to create D3D11 device for target.");
}
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()) {
throw std::runtime_error("OBS Device is not a D3D11 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;
device->GetImmediateContext(&context);
@ -146,16 +156,15 @@ struct D3D11AVFrame {
ATL::CComPtr<ID3D11Texture2D> handle;
};
obsffmpeg::hwapi::d3d11_instance::d3d11_instance(ATL::CComPtr<ID3D11Device> device,
ATL::CComPtr<ID3D11DeviceContext> context)
d3d11_instance::d3d11_instance(ATL::CComPtr<ID3D11Device> device, ATL::CComPtr<ID3D11DeviceContext> context)
{
_device = device;
_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);
if (!dctx_ref)
@ -179,9 +188,9 @@ AVBufferRef* obsffmpeg::hwapi::d3d11_instance::create_device_context()
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) {
av_frame_unref(frame);
@ -195,16 +204,16 @@ std::shared_ptr<AVFrame> obsffmpeg::hwapi::d3d11_instance::allocate_frame(AVBuff
return frame;
}
void obsffmpeg::hwapi::d3d11_instance::copy_from_obs(AVBufferRef*, uint32_t handle, uint64_t lock_key,
uint64_t* next_lock_key, std::shared_ptr<AVFrame> frame)
void d3d11_instance::copy_from_obs(AVBufferRef*, uint32_t handle, uint64_t lock_key, uint64_t* next_lock_key,
std::shared_ptr<AVFrame> frame)
{
auto gctx = obsffmpeg::obs_graphics();
auto gctx = util::obs_graphics();
ATL::CComPtr<IDXGIKeyedMutex> mutex;
ATL::CComPtr<ID3D11Texture2D> input;
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.");
}
@ -234,12 +243,14 @@ void obsffmpeg::hwapi::d3d11_instance::copy_from_obs(AVBufferRef*, uint32_t hand
mutex->ReleaseSync(*next_lock_key);
}
std::shared_ptr<AVFrame> obsffmpeg::hwapi::d3d11_instance::avframe_from_obs(AVBufferRef* frames, uint32_t handle,
uint64_t lock_key, uint64_t* next_lock_key)
std::shared_ptr<AVFrame> d3d11_instance::avframe_from_obs(AVBufferRef* frames, uint32_t handle, uint64_t lock_key,
uint64_t* next_lock_key)
{
auto gctx = obsffmpeg::obs_graphics();
auto gctx = util::obs_graphics();
auto frame = this->allocate_frame(frames);
this->copy_from_obs(frames, handle, lock_key, next_lock_key, frame);
return frame;
}
#endif

View file

@ -19,62 +19,68 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// 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 <d3d11.h>
#include <d3d11_1.h>
#include <dxgi.h>
#include "base.hpp"
#pragma warning(pop)
}
namespace obsffmpeg {
namespace hwapi {
class d3d11 : public ::obsffmpeg::hwapi::base {
typedef HRESULT(__stdcall* CreateDXGIFactory_t)(REFIID, void**);
typedef HRESULT(__stdcall* CreateDXGIFactory1_t)(REFIID, void**);
typedef HRESULT(__stdcall* D3D11CreateDevice_t)(_In_opt_ IDXGIAdapter*, D3D_DRIVER_TYPE,
HMODULE, UINT, CONST D3D_FEATURE_LEVEL*, UINT,
UINT, _Out_opt_ ID3D11Device**,
_Out_opt_ D3D_FEATURE_LEVEL*,
_Out_opt_ ID3D11DeviceContext**);
namespace ffmpeg::hwapi {
class d3d11 : public ffmpeg::hwapi::base {
typedef HRESULT(__stdcall* CreateDXGIFactory_t)(REFIID, void**);
typedef HRESULT(__stdcall* CreateDXGIFactory1_t)(REFIID, void**);
typedef HRESULT(__stdcall* D3D11CreateDevice_t)(IDXGIAdapter*, D3D_DRIVER_TYPE, HMODULE, UINT,
CONST D3D_FEATURE_LEVEL*, UINT, UINT, ID3D11Device**,
D3D_FEATURE_LEVEL*, ID3D11DeviceContext**);
HMODULE _dxgi_module;
CreateDXGIFactory_t _CreateDXGIFactory;
CreateDXGIFactory1_t _CreateDXGIFactory1;
HMODULE _dxgi_module;
CreateDXGIFactory_t _CreateDXGIFactory;
CreateDXGIFactory1_t _CreateDXGIFactory1;
HMODULE _d3d11_module;
D3D11CreateDevice_t _D3D11CreateDevice;
HMODULE _d3d11_module;
D3D11CreateDevice_t _D3D11CreateDevice;
ATL::CComPtr<IDXGIFactory1> _dxgifactory;
ATL::CComPtr<IDXGIFactory1> _dxgifactory;
public:
d3d11();
virtual ~d3d11();
public:
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>
create(obsffmpeg::hwapi::device target) override;
virtual std::shared_ptr<hwapi::instance> create(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 {
ATL::CComPtr<ID3D11Device> _device;
ATL::CComPtr<ID3D11DeviceContext> _context;
class d3d11_instance : public ffmpeg::hwapi::instance {
ATL::CComPtr<ID3D11Device> _device;
ATL::CComPtr<ID3D11DeviceContext> _context;
public:
d3d11_instance(ATL::CComPtr<ID3D11Device> device, ATL::CComPtr<ID3D11DeviceContext> context);
virtual ~d3d11_instance();
public:
d3d11_instance(ATL::CComPtr<ID3D11Device> device, ATL::CComPtr<ID3D11DeviceContext> context);
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,
uint64_t* next_lock_key, std::shared_ptr<AVFrame> frame) override;
virtual void copy_from_obs(AVBufferRef* frames, uint32_t handle, uint64_t lock_key, uint64_t* next_lock_key,
std::shared_ptr<AVFrame> frame) override;
virtual std::shared_ptr<AVFrame> avframe_from_obs(AVBufferRef* frames, uint32_t handle,
uint64_t lock_key,
uint64_t* next_lock_key) override;
};
} // namespace hwapi
} // namespace obsffmpeg
virtual std::shared_ptr<AVFrame> avframe_from_obs(AVBufferRef* frames, uint32_t handle, uint64_t lock_key,
uint64_t* next_lock_key) override;
};
} // namespace ffmpeg::hwapi

View file

@ -22,167 +22,169 @@
#include "swscale.hpp"
#include <stdexcept>
ffmpeg::swscale::swscale() {}
using namespace ffmpeg;
ffmpeg::swscale::~swscale()
swscale::swscale() {}
swscale::~swscale()
{
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.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;
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;
}
uint32_t ffmpeg::swscale::get_source_width()
uint32_t swscale::get_source_width()
{
return this->source_size.first;
}
uint32_t ffmpeg::swscale::get_source_height()
uint32_t swscale::get_source_height()
{
return this->source_size.second;
}
void ffmpeg::swscale::set_source_format(AVPixelFormat format)
void swscale::set_source_format(AVPixelFormat format)
{
source_format = format;
}
AVPixelFormat ffmpeg::swscale::get_source_format()
AVPixelFormat swscale::get_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_colorspace = space;
}
void ffmpeg::swscale::set_source_colorspace(AVColorSpace space)
void swscale::set_source_colorspace(AVColorSpace space)
{
this->source_colorspace = space;
}
AVColorSpace ffmpeg::swscale::get_source_colorspace()
AVColorSpace swscale::get_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;
}
bool ffmpeg::swscale::is_source_full_range()
bool swscale::is_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.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;
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;
}
uint32_t ffmpeg::swscale::get_target_width()
uint32_t swscale::get_target_width()
{
return this->target_size.first;
}
uint32_t ffmpeg::swscale::get_target_height()
uint32_t swscale::get_target_height()
{
return this->target_size.second;
}
void ffmpeg::swscale::set_target_format(AVPixelFormat format)
void swscale::set_target_format(AVPixelFormat format)
{
target_format = format;
}
AVPixelFormat ffmpeg::swscale::get_target_format()
AVPixelFormat swscale::get_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_colorspace = space;
}
void ffmpeg::swscale::set_target_colorspace(AVColorSpace space)
void swscale::set_target_colorspace(AVColorSpace space)
{
this->target_colorspace = space;
}
AVColorSpace ffmpeg::swscale::get_target_colorspace()
AVColorSpace swscale::get_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;
}
bool ffmpeg::swscale::is_target_full_range()
bool swscale::is_target_full_range()
{
return this->target_full_range;
}
bool ffmpeg::swscale::initialize(int flags)
bool swscale::initialize(int flags)
{
if (this->context) {
return false;
}
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");
}
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");
}
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) {
return false;
}
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,
1L << 16 | 0L, 1L << 16 | 0L);
sws_getCoefficients(target_colorspace), target_full_range ? 1 : 0, 1L << 16 | 0L,
1L << 16 | 0L, 1L << 16 | 0L);
return true;
}
bool ffmpeg::swscale::finalize()
bool swscale::finalize()
{
if (this->context) {
sws_freeContext(this->context);
@ -192,13 +194,13 @@ bool ffmpeg::swscale::finalize()
return false;
}
int32_t ffmpeg::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 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[])
{
if (!this->context) {
return 0;
}
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;
}

View file

@ -19,10 +19,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef OBS_FFMPEG_FFMPEG_SWSCALE
#define OBS_FFMPEG_FFMPEG_SWSCALE
#pragma once
#include <cinttypes>
#include <utility>
@ -82,8 +79,6 @@ namespace ffmpeg {
bool finalize();
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
#endif OBS_FFMPEG_FFMPEG_SWSCALE

View file

@ -37,26 +37,28 @@ extern "C" {
#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.
std::pair<int, std::string> caps[] = {
{AV_CODEC_CAP_EXPERIMENTAL, "Experimental"},
{AV_CODEC_CAP_EXPERIMENTAL, "Experimental"},
// Quality
{AV_CODEC_CAP_LOSSLESS, "Lossless"},
// Quality
{AV_CODEC_CAP_LOSSLESS, "Lossless"},
// Features
{AV_CODEC_CAP_PARAM_CHANGE, "Dynamic Parameter Change"},
{AV_CODEC_CAP_SUBFRAMES, "Sub-Frames"},
{AV_CODEC_CAP_VARIABLE_FRAME_SIZE, "Variable Frame Size"},
{AV_CODEC_CAP_SMALL_LAST_FRAME, "Small Final Frame"},
// Features
{AV_CODEC_CAP_PARAM_CHANGE, "Dynamic Parameter Change"},
{AV_CODEC_CAP_SUBFRAMES, "Sub-Frames"},
{AV_CODEC_CAP_VARIABLE_FRAME_SIZE, "Variable Frame Size"},
{AV_CODEC_CAP_SMALL_LAST_FRAME, "Small Final Frame"},
// Other
{AV_CODEC_CAP_TRUNCATED, "Truncated"},
{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_AVOID_PROBING, "AV_CODEC_CAP_AVOID_PROBING"},
// Other
{AV_CODEC_CAP_TRUNCATED, "Truncated"},
{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_AVOID_PROBING, "AV_CODEC_CAP_AVOID_PROBING"},
};
std::stringstream sstr;
@ -75,12 +77,12 @@ std::string ffmpeg::tools::translate_encoder_capabilities(int capabilities)
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);
}
const char* ffmpeg::tools::get_color_space_name(AVColorSpace v)
const char* tools::get_color_space_name(AVColorSpace v)
{
switch (v) {
case AVCOL_SPC_RGB:
@ -114,7 +116,7 @@ const char* ffmpeg::tools::get_color_space_name(AVColorSpace v)
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];
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;
}
static std::map<video_format, AVPixelFormat> obs_to_av_format_map = {
{VIDEO_FORMAT_I420, AV_PIX_FMT_YUV420P}, // YUV 4:2:0
{VIDEO_FORMAT_NV12, AV_PIX_FMT_NV12}, // NV12 Packed YUV
{VIDEO_FORMAT_YVYU, AV_PIX_FMT_YVYU422}, // YVYU Packed YUV
{VIDEO_FORMAT_YUY2, AV_PIX_FMT_YUYV422}, // YUYV Packed YUV
{VIDEO_FORMAT_UYVY, AV_PIX_FMT_UYVY422}, // UYVY Packed YUV
{VIDEO_FORMAT_RGBA, AV_PIX_FMT_RGBA}, //
{VIDEO_FORMAT_BGRA, AV_PIX_FMT_BGRA}, //
{VIDEO_FORMAT_BGRX, AV_PIX_FMT_BGR0}, //
{VIDEO_FORMAT_Y800, AV_PIX_FMT_GRAY8}, //
{VIDEO_FORMAT_I444, AV_PIX_FMT_YUV444P}, //
{VIDEO_FORMAT_BGR3, AV_PIX_FMT_BGR24}, //
{VIDEO_FORMAT_I422, AV_PIX_FMT_YUV422P}, //
{VIDEO_FORMAT_I40A, AV_PIX_FMT_YUVA420P}, //
{VIDEO_FORMAT_I42A, AV_PIX_FMT_YUVA422P}, //
{VIDEO_FORMAT_YUVA, AV_PIX_FMT_YUVA444P}, //
//{VIDEO_FORMAT_AYUV, AV_PIX_FMT_AYUV444P}, //
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_NV12, AV_PIX_FMT_NV12}, // NV12 Packed YUV
{VIDEO_FORMAT_YVYU, AV_PIX_FMT_YVYU422}, // YVYU Packed YUV
{VIDEO_FORMAT_YUY2, AV_PIX_FMT_YUYV422}, // YUYV Packed YUV
{VIDEO_FORMAT_UYVY, AV_PIX_FMT_UYVY422}, // UYVY Packed YUV
{VIDEO_FORMAT_RGBA, AV_PIX_FMT_RGBA}, //
{VIDEO_FORMAT_BGRA, AV_PIX_FMT_BGRA}, //
{VIDEO_FORMAT_BGRX, AV_PIX_FMT_BGR0}, //
{VIDEO_FORMAT_Y800, AV_PIX_FMT_GRAY8}, //
{VIDEO_FORMAT_I444, AV_PIX_FMT_YUV444P}, //
{VIDEO_FORMAT_BGR3, AV_PIX_FMT_BGR24}, //
{VIDEO_FORMAT_I422, AV_PIX_FMT_YUV422P}, //
{VIDEO_FORMAT_I40A, AV_PIX_FMT_YUVA420P}, //
{VIDEO_FORMAT_I42A, AV_PIX_FMT_YUVA422P}, //
{VIDEO_FORMAT_YUVA, AV_PIX_FMT_YUVA444P}, //
//{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);
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;
}
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) {
if (kv.second == v)
@ -160,13 +162,13 @@ video_format ffmpeg::tools::avpixelformat_to_obs_videoformat(AVPixelFormat v)
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;
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) {
case VIDEO_CS_DEFAULT:
@ -178,7 +180,7 @@ AVColorSpace ffmpeg::tools::obs_videocolorspace_to_avcolorspace(video_colorspace
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) {
case VIDEO_RANGE_DEFAULT:
@ -190,7 +192,7 @@ AVColorRange ffmpeg::tools::obs_videorangetype_to_avcolorrange(video_range_type
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};
@ -204,7 +206,7 @@ bool ffmpeg::tools::can_hardware_encode(const AVCodec* codec)
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[] = {
#if FF_API_VAAPI
@ -241,18 +243,18 @@ std::vector<AVPixelFormat> ffmpeg::tools::get_software_formats(const AVPixelForm
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>>
colorspaces = {
{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_709, {AVCOL_SPC_BT709, AVCOL_PRI_BT709, AVCOL_TRC_BT709}},
};
std::map<video_colorspace, std::tuple<AVColorSpace, AVColorPrimaries, AVColorTransferCharacteristic>> colorspaces =
{
{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_709, {AVCOL_SPC_BT709, AVCOL_PRI_BT709, AVCOL_TRC_BT709}},
};
std::map<video_range_type, AVColorRange> colorranges = {
{VIDEO_RANGE_DEFAULT, AVCOL_RANGE_MPEG},
{VIDEO_RANGE_PARTIAL, AVCOL_RANGE_MPEG},
{VIDEO_RANGE_FULL, AVCOL_RANGE_JPEG},
{VIDEO_RANGE_DEFAULT, AVCOL_RANGE_MPEG},
{VIDEO_RANGE_PARTIAL, AVCOL_RANGE_MPEG},
{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;
}
const char* ffmpeg::tools::get_std_compliance_name(int compliance)
const char* tools::get_std_compliance_name(int compliance)
{
switch (compliance) {
case FF_COMPLIANCE_VERY_STRICT:
@ -291,7 +293,7 @@ const char* ffmpeg::tools::get_std_compliance_name(int compliance)
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) {
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) {
int64_t 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 {
PLOG_INFO("[%s] %s: <Error>", context->codec->name, text.c_str());
LOG_INFO("[%s] %s: <Error>", context->codec->name, text.c_str());
}
} 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,
std::string suffix)
void tools::print_av_option_int(AVCodecContext* context, const char* option, std::string text, std::string suffix)
{
if (av_opt_is_set_to_default_by_name(context, option, AV_OPT_SEARCH_CHILDREN) == 0) {
int64_t 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 {
PLOG_INFO("[%s] %s: <Error>", context->codec->name, text.c_str());
LOG_INFO("[%s] %s: <Error>", context->codec->name, text.c_str());
}
} 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,
std::function<std::string(int64_t)> decoder)
void tools::print_av_option_string(AVCodecContext* context, const char* option, std::string text,
std::function<std::string(int64_t)> decoder)
{
if (av_opt_is_set_to_default_by_name(context, option, AV_OPT_SEARCH_CHILDREN) == 0) {
int64_t v = 0;
@ -343,11 +344,11 @@ void ffmpeg::tools::print_av_option_string(AVCodecContext* context, const char*
std::string name = "<Unknown>";
if (decoder)
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 {
PLOG_INFO("[%s] %s: <Error>", context->codec->name, text.c_str());
LOG_INFO("[%s] %s: <Error>", context->codec->name, text.c_str());
}
} else {
PLOG_INFO("[%s] %s: <Default>", context->codec->name, text.c_str());
LOG_INFO("[%s] %s: <Default>", context->codec->name, text.c_str());
}
}

View file

@ -19,10 +19,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef OBS_FFMPEG_FFMPEG_UTILITY
#define OBS_FFMPEG_FFMPEG_UTILITY
#pragma once
#include <functional>
#include <obs.h>
#include <string>
@ -33,45 +30,40 @@ extern "C" {
#include <libavutil/pixfmt.h>
}
namespace ffmpeg {
namespace tools {
std::string translate_encoder_capabilities(int capabilities);
namespace ffmpeg::tools {
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,
std::string suffix);
void print_av_option_int(AVCodecContext* context, const char* option, std::string text, std::string suffix);
void print_av_option_string(AVCodecContext* context, const char* option, std::string text,
std::function<std::string(int64_t)> decoder);
void print_av_option_string(AVCodecContext* context, const char* option, std::string text,
std::function<std::string(int64_t)> decoder);
} // namespace tools
} // namespace ffmpeg
#endif OBS_FFMPEG_FFMPEG_UTILITY
} // namespace ffmpeg::tools

View file

@ -77,6 +77,8 @@
#define ST_MASK_ALPHA "Filter.Blur.Mask.Alpha"
#define ST_MASK_MULTIPLIER "Filter.Blur.Mask.Multiplier"
using namespace filter;
struct local_blur_type_t {
std::function<::gfx::blur::ifactory&()> fn;
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}},
};
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)
{
{
@ -118,7 +120,7 @@ filter::blur::blur_instance::blur_instance(obs_data_t* settings, obs_source_t* s
try {
_effect_mask = gs::effect::create(file);
} 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);
@ -128,10 +130,10 @@ filter::blur::blur_instance::blur_instance(obs_data_t* settings, obs_source_t* s
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,
gs_texture_t* blurred_texture)
bool blur::blur_instance::apply_mask_parameters(gs::effect effect, gs_texture_t* original_texture,
gs_texture_t* blurred_texture)
{
if (effect.has_parameter("image_orig")) {
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_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.
migrate_settings(settings);
@ -276,7 +278,7 @@ void filter::blur::blur_instance::update(obs_data_t* settings)
{ // Masking
_mask.enabled = obs_data_get_bool(settings, ST_MASK);
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) {
case mask_type::Region:
_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);
}
void filter::blur::blur_instance::video_tick(float)
void blur::blur_instance::video_tick(float)
{
// 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.path_old = _mask.image.path;
} catch (...) {
P_LOG_ERROR("<filter-blur> Instance '%s' failed to load image '%s'.", obs_source_get_name(_self),
_mask.image.path.c_str());
LOG_ERROR("<filter-blur> Instance '%s' failed to load image '%s'.", obs_source_get_name(_self),
_mask.image.path.c_str());
}
}
} 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.name_old = _mask.source.name;
} catch (...) {
P_LOG_ERROR("<filter-blur> Instance '%s' failed to grab source '%s'.", obs_source_get_name(_self),
_mask.source.name.c_str());
LOG_ERROR("<filter-blur> Instance '%s' failed to grab source '%s'.", obs_source_get_name(_self),
_mask.source.name.c_str());
}
}
}
@ -361,7 +363,7 @@ void filter::blur::blur_instance::video_tick(float)
_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* 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");
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);
return;
} 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.type = OBS_SOURCE_TYPE_FILTER;
@ -551,14 +553,14 @@ filter::blur::blur_factory::blur_factory()
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);
}
void filter::blur::blur_factory::get_defaults2(obs_data_t* settings)
void blur::blur_factory::get_defaults2(obs_data_t* settings)
{
// Type, Subtype
obs_data_set_default_string(settings, ST_TYPE, "box");
@ -731,7 +733,7 @@ try {
}
{ // Masking
using namespace filter::blur;
using namespace blur;
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));
bool show_region = (mtype == mask_type::Region) && show_mask;
@ -754,11 +756,11 @@ try {
return true;
} catch (...) {
P_LOG_ERROR("Unexpected exception in modified_properties callback.");
LOG_ERROR("Unexpected exception in modified_properties callback.");
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_property_t* p = NULL;
@ -877,7 +879,7 @@ obs_properties_t* filter::blur::blur_factory::get_properties2(filter::blur::blur
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_start(vargs, format);

View file

@ -42,119 +42,116 @@
#pragma warning(pop)
#endif
namespace filter {
namespace blur {
enum class mask_type : int64_t {
Region,
Image,
Source,
};
namespace filter::blur {
enum class mask_type : int64_t {
Region,
Image,
Source,
};
class blur_instance : public obs::source_instance {
// Effects
gs::effect _effect_mask;
class blur_instance : public obs::source_instance {
// Effects
gs::effect _effect_mask;
// Input
std::shared_ptr<gs::rendertarget> _source_rt;
std::shared_ptr<gs::texture> _source_texture;
bool _source_rendered;
// Input
std::shared_ptr<gs::rendertarget> _source_rt;
std::shared_ptr<gs::texture> _source_texture;
bool _source_rendered;
// Rendering
std::shared_ptr<gs::texture> _output_texture;
std::shared_ptr<gs::rendertarget> _output_rt;
bool _output_rendered;
// Rendering
std::shared_ptr<gs::texture> _output_texture;
std::shared_ptr<gs::rendertarget> _output_rt;
bool _output_rendered;
// Blur
std::shared_ptr<::gfx::blur::base> _blur;
double_t _blur_size;
double_t _blur_angle;
std::pair<double_t, double_t> _blur_center;
bool _blur_step_scaling;
std::pair<double_t, double_t> _blur_step_scale;
// Blur
std::shared_ptr<::gfx::blur::base> _blur;
double_t _blur_size;
double_t _blur_angle;
std::pair<double_t, double_t> _blur_center;
bool _blur_step_scaling;
std::pair<double_t, double_t> _blur_step_scale;
// Masking
// Masking
struct {
bool enabled;
mask_type type;
struct {
bool enabled;
mask_type type;
struct {
float_t left;
float_t top;
float_t right;
float_t bottom;
float_t feather;
float_t feather_shift;
bool invert;
} region;
struct {
std::string path;
std::string path_old;
std::shared_ptr<gs::texture> texture;
} image;
struct {
std::string name_old;
std::string name;
bool is_scene;
std::shared_ptr<gfx::source_texture> source_texture;
std::shared_ptr<gs::texture> texture;
} source;
struct {
float_t r;
float_t g;
float_t b;
float_t a;
} color;
float_t multiplier;
} _mask;
float_t left;
float_t top;
float_t right;
float_t bottom;
float_t feather;
float_t feather_shift;
bool invert;
} region;
struct {
std::string path;
std::string path_old;
std::shared_ptr<gs::texture> texture;
} image;
struct {
std::string name_old;
std::string name;
bool is_scene;
std::shared_ptr<gfx::source_texture> source_texture;
std::shared_ptr<gs::texture> texture;
} source;
struct {
float_t r;
float_t g;
float_t b;
float_t a;
} color;
float_t multiplier;
} _mask;
public:
blur_instance(obs_data_t* settings, obs_source_t* self);
~blur_instance();
public:
blur_instance(obs_data_t* settings, obs_source_t* self);
~blur_instance();
public:
virtual void update(obs_data_t* settings) override;
virtual void load(obs_data_t* settings) override;
public:
virtual void update(obs_data_t* settings) override;
virtual void load(obs_data_t* settings) override;
virtual void video_tick(float time) override;
virtual void video_render(gs_effect_t* effect) override;
virtual void video_tick(float time) override;
virtual void video_render(gs_effect_t* effect) override;
private:
bool apply_mask_parameters(gs::effect effect, gs_texture_t* original_texture,
gs_texture_t* blurred_texture);
};
private:
bool apply_mask_parameters(gs::effect effect, gs_texture_t* original_texture, gs_texture_t* blurred_texture);
};
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;
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;
public: // Singleton
static void initialize()
{
factory_instance = std::make_shared<filter::blur::blur_factory>();
}
public: // Singleton
static void initialize()
{
factory_instance = std::make_shared<filter::blur::blur_factory>();
}
static void finalize()
{
factory_instance.reset();
}
static void finalize()
{
factory_instance.reset();
}
static std::shared_ptr<blur_factory> get()
{
return factory_instance;
}
static std::shared_ptr<blur_factory> get()
{
return factory_instance;
}
private:
std::vector<std::string> _translation_cache;
private:
std::vector<std::string> _translation_cache;
public:
blur_factory();
virtual ~blur_factory();
public:
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, ...);
};
} // namespace blur
} // namespace filter
std::string translate_string(const char* format, ...);
};
} // namespace filter::blur

View file

@ -74,9 +74,11 @@
#define MODE_LOG Log
#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)
{
{
@ -86,7 +88,7 @@ filter::color_grade::color_grade_instance::color_grade_instance(obs_data_t* data
_effect = gs::effect::create(file);
bfree(file);
} 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);
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);
}
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.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);
}
void filter::color_grade::color_grade_instance::video_tick(float)
void color_grade::color_grade_instance::video_tick(float)
{
_source_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.
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 =
nullptr;
std::shared_ptr<color_grade::color_grade_factory> color_grade::color_grade_factory::factory_instance = 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.type = OBS_SOURCE_TYPE_FILTER;
@ -265,14 +266,14 @@ filter::color_grade::color_grade_factory::color_grade_factory()
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);
}
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_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_(BLUE), 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_DETECTION,
static_cast<int64_t>(filter::color_grade::detection_mode::YUV_SDR));
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, static_cast<int64_t>(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_(TONE_LOW, RED), 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_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();
@ -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,
OBS_COMBO_FORMAT_INT);
std::pair<const char*, filter::color_grade::luma_mode> els[] = {
{ST_TINT_MODE_(MODE_LINEAR), filter::color_grade::luma_mode::Linear},
{ST_TINT_MODE_(MODE_EXP), filter::color_grade::luma_mode::Exp},
{ST_TINT_MODE_(MODE_EXP2), filter::color_grade::luma_mode::Exp2},
{ST_TINT_MODE_(MODE_LOG), filter::color_grade::luma_mode::Log},
{ST_TINT_MODE_(MODE_LOG10), filter::color_grade::luma_mode::Log10}};
std::pair<const char*, color_grade::luma_mode> els[] = {
{ST_TINT_MODE_(MODE_LINEAR), color_grade::luma_mode::Linear},
{ST_TINT_MODE_(MODE_EXP), color_grade::luma_mode::Exp},
{ST_TINT_MODE_(MODE_EXP2), color_grade::luma_mode::Exp2},
{ST_TINT_MODE_(MODE_LOG), color_grade::luma_mode::Log},
{ST_TINT_MODE_(MODE_LOG10), color_grade::luma_mode::Log10}};
for (auto kv : els) {
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),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
std::pair<const char*, filter::color_grade::detection_mode> els[] = {
{ST_TINT_DETECTION_(DETECTION_HSV), filter::color_grade::detection_mode::HSV},
{ST_TINT_DETECTION_(DETECTION_HSL), filter::color_grade::detection_mode::HSL},
{ST_TINT_DETECTION_(DETECTION_YUV_SDR), filter::color_grade::detection_mode::YUV_SDR}};
std::pair<const char*, color_grade::detection_mode> els[] = {
{ST_TINT_DETECTION_(DETECTION_HSV), color_grade::detection_mode::HSV},
{ST_TINT_DETECTION_(DETECTION_HSL), color_grade::detection_mode::HSL},
{ST_TINT_DETECTION_(DETECTION_YUV_SDR), color_grade::detection_mode::YUV_SDR}};
for (auto kv : els) {
obs_property_list_add_int(p, D_TRANSLATE(kv.first), static_cast<int64_t>(kv.second));
}

View file

@ -27,88 +27,86 @@
#include "obs/obs-source-factory.hpp"
#include "plugin.hpp"
namespace filter {
namespace color_grade {
enum class detection_mode {
HSV,
HSL,
YUV_SDR,
};
namespace filter::color_grade {
enum class detection_mode {
HSV,
HSL,
YUV_SDR,
};
enum class luma_mode {
Linear,
Exp,
Exp2,
Log,
Log10,
};
enum class luma_mode {
Linear,
Exp,
Exp2,
Log,
Log10,
};
class color_grade_instance : public obs::source_instance {
gs::effect _effect;
class color_grade_instance : public obs::source_instance {
gs::effect _effect;
// Source
std::unique_ptr<gs::rendertarget> _rt_source;
std::shared_ptr<gs::texture> _tex_source;
bool _source_updated;
// Source
std::unique_ptr<gs::rendertarget> _rt_source;
std::shared_ptr<gs::texture> _tex_source;
bool _source_updated;
// Grading
std::unique_ptr<gs::rendertarget> _rt_grade;
std::shared_ptr<gs::texture> _tex_grade;
bool _grade_updated;
// Grading
std::unique_ptr<gs::rendertarget> _rt_grade;
std::shared_ptr<gs::texture> _tex_grade;
bool _grade_updated;
// Parameters
vec4 _lift;
vec4 _gamma;
vec4 _gain;
vec4 _offset;
detection_mode _tint_detection;
luma_mode _tint_luma;
float_t _tint_exponent;
vec3 _tint_low;
vec3 _tint_mid;
vec3 _tint_hig;
vec4 _correction;
// Parameters
vec4 _lift;
vec4 _gamma;
vec4 _gain;
vec4 _offset;
detection_mode _tint_detection;
luma_mode _tint_luma;
float_t _tint_exponent;
vec3 _tint_low;
vec3 _tint_mid;
vec3 _tint_hig;
vec4 _correction;
public:
color_grade_instance(obs_data_t* data, obs_source_t* self);
virtual ~color_grade_instance();
public:
color_grade_instance(obs_data_t* data, obs_source_t* self);
virtual ~color_grade_instance();
virtual void load(obs_data_t* data) override;
virtual void update(obs_data_t* data) override;
virtual void load(obs_data_t* data) override;
virtual void update(obs_data_t* data) override;
virtual void video_tick(float time) override;
virtual void video_render(gs_effect_t* effect) override;
};
virtual void video_tick(float time) override;
virtual void video_render(gs_effect_t* effect) override;
};
class color_grade_factory : public obs::source_factory<filter::color_grade::color_grade_factory,
filter::color_grade::color_grade_instance> {
static std::shared_ptr<filter::color_grade::color_grade_factory> factory_instance;
class color_grade_factory : public obs::source_factory<filter::color_grade::color_grade_factory,
filter::color_grade::color_grade_instance> {
static std::shared_ptr<filter::color_grade::color_grade_factory> factory_instance;
public: // Singleton
static void initialize()
{
factory_instance = std::make_shared<filter::color_grade::color_grade_factory>();
}
public: // Singleton
static void initialize()
{
factory_instance = std::make_shared<filter::color_grade::color_grade_factory>();
}
static void finalize()
{
factory_instance.reset();
}
static void finalize()
{
factory_instance.reset();
}
static std::shared_ptr<color_grade_factory> get()
{
return factory_instance;
}
static std::shared_ptr<color_grade_factory> get()
{
return factory_instance;
}
public:
color_grade_factory();
virtual ~color_grade_factory();
public:
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;
};
} // namespace color_grade
} // namespace filter
virtual obs_properties_t* get_properties2(color_grade_instance* data) override;
};
} // namespace filter::color_grade

View file

@ -27,7 +27,9 @@
#define ST_SCALE "Filter.Displacement.Scale"
#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)
{
std::string effect = "";
@ -42,12 +44,12 @@ filter::displacement::displacement_instance::displacement_instance(obs_data_t* d
update(data);
}
filter::displacement::displacement_instance::~displacement_instance()
displacement::displacement_instance::~displacement_instance()
{
_texture.reset();
}
void filter::displacement::displacement_instance::load(obs_data_t* settings)
void displacement::displacement_instance::load(obs_data_t* 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));
switch (version & STREAMEFFECTS_MASK_COMPAT) {
switch (version & STREAMFX_MASK_COMPAT) {
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_TYPE,
obs_data_get_double(settings, "Filter.Displacement.Ratio") * 100.0);
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;
}
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);
@ -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);
_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.
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);
}
std::string filter::displacement::displacement_instance::get_file()
std::string displacement::displacement_instance::get_file()
{
return _texture_file;
}
std::shared_ptr<filter::displacement::displacement_factory>
filter::displacement::displacement_factory::factory_instance = nullptr;
std::shared_ptr<displacement::displacement_factory> 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.type = OBS_SOURCE_TYPE_FILTER;
@ -133,14 +134,14 @@ filter::displacement::displacement_factory::displacement_factory()
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);
}
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");
@ -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_properties_t*
filter::displacement::displacement_factory::get_properties2(filter::displacement::displacement_instance* data)
obs_properties_t* displacement::displacement_factory::get_properties2(displacement::displacement_instance* data)
{
obs_properties_t* pr = obs_properties_create();

View file

@ -35,63 +35,61 @@
#pragma warning(pop)
#endif
namespace filter {
namespace displacement {
class displacement_instance : public obs::source_instance {
gs::effect _effect;
namespace filter::displacement {
class displacement_instance : public obs::source_instance {
gs::effect _effect;
// Displacement Map
std::shared_ptr<gs::texture> _texture;
std::string _texture_file;
float_t _scale[2];
float_t _scale_type;
// Displacement Map
std::shared_ptr<gs::texture> _texture;
std::string _texture_file;
float_t _scale[2];
float_t _scale_type;
// Cache
uint32_t _width;
uint32_t _height;
// Cache
uint32_t _width;
uint32_t _height;
public:
displacement_instance(obs_data_t*, obs_source_t*);
virtual ~displacement_instance();
public:
displacement_instance(obs_data_t*, obs_source_t*);
virtual ~displacement_instance();
virtual void load(obs_data_t* settings) override;
virtual void update(obs_data_t* settings) override;
virtual void load(obs_data_t* settings) override;
virtual void update(obs_data_t* settings) override;
virtual void video_tick(float_t) override;
virtual void video_render(gs_effect_t*) override;
virtual void video_tick(float_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,
filter::displacement::displacement_instance> {
static std::shared_ptr<filter::displacement::displacement_factory> factory_instance;
class displacement_factory : public obs::source_factory<filter::displacement::displacement_factory,
filter::displacement::displacement_instance> {
static std::shared_ptr<filter::displacement::displacement_factory> factory_instance;
public: // Singleton
static void initialize()
{
factory_instance = std::make_shared<filter::displacement::displacement_factory>();
}
public: // Singleton
static void initialize()
{
factory_instance = std::make_shared<filter::displacement::displacement_factory>();
}
static void finalize()
{
factory_instance.reset();
}
static void finalize()
{
factory_instance.reset();
}
static std::shared_ptr<displacement_factory> get()
{
return factory_instance;
}
static std::shared_ptr<displacement_factory> get()
{
return factory_instance;
}
public:
displacement_factory();
virtual ~displacement_factory();
public:
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;
};
} // namespace displacement
} // namespace filter
virtual obs_properties_t* get_properties2(filter::displacement::displacement_instance* data) override;
};
} // namespace filter::displacement

View file

@ -39,17 +39,18 @@
#define ST_CHANNEL_MULTIPLIER "Filter.DynamicMask.Channel.Multiplier"
#define ST_CHANNEL_INPUT "Filter.DynamicMask.Channel.Input"
std::shared_ptr<filter::dynamic_mask::dynamic_mask_factory>
filter::dynamic_mask::dynamic_mask_factory::factory_instance = nullptr;
using namespace filter;
static std::pair<filter::dynamic_mask::channel, const char*> channel_translations[] = {
{filter::dynamic_mask::channel::Red, S_CHANNEL_RED},
{filter::dynamic_mask::channel::Green, S_CHANNEL_GREEN},
{filter::dynamic_mask::channel::Blue, S_CHANNEL_BLUE},
{filter::dynamic_mask::channel::Alpha, S_CHANNEL_ALPHA},
std::shared_ptr<dynamic_mask::dynamic_mask_factory> dynamic_mask::dynamic_mask_factory::factory_instance = nullptr;
static std::pair<dynamic_mask::channel, const char*> channel_translations[] = {
{dynamic_mask::channel::Red, S_CHANNEL_RED},
{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),
_have_final_texture(false), _precalc(), _effect()
{
@ -61,7 +62,7 @@ filter::dynamic_mask::dynamic_mask_instance::dynamic_mask_instance(obs_data_t* s
try {
_effect = gs::effect::create(file);
} 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);
bfree(file);
@ -70,15 +71,15 @@ filter::dynamic_mask::dynamic_mask_instance::dynamic_mask_instance(obs_data_t* s
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.
try {
_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->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);
} catch (...) {
_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);
}
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) {
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,
std::string new_name)
void dynamic_mask::dynamic_mask_instance::input_renamed(obs::deprecated_source*, std::string old_name,
std::string new_name)
{
obs_data_t* settings = obs_source_get_settings(_self);
obs_data_set_string(settings, ST_INPUT, new_name.c_str());
obs_source_update(_self, settings);
}
bool filter::dynamic_mask::dynamic_mask_instance::modified(void*, obs_properties_t* properties, obs_property_t*,
obs_data_t* settings) noexcept
bool dynamic_mask::dynamic_mask_instance::modified(void*, obs_properties_t* properties, obs_property_t*,
obs_data_t* settings) noexcept
try {
channel mask = static_cast<channel>(obs_data_get_int(settings, ST_CHANNEL));
@ -196,21 +197,21 @@ try {
return true;
} 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;
} catch (...) {
P_LOG_ERROR("Unexpected exception in modified_properties callback.");
LOG_ERROR("Unexpected exception in modified_properties callback.");
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_filter_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* 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_eparam_t* param = gs_effect_get_param_by_name(final_effect, "image");
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);
return;
} 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.type = OBS_SOURCE_TYPE_FILTER;
@ -355,16 +356,16 @@ filter::dynamic_mask::dynamic_mask_factory::dynamic_mask_factory()
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);
}
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) {
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);
@ -375,8 +376,7 @@ void filter::dynamic_mask::dynamic_mask_factory::get_defaults2(obs_data_t* data)
}
}
obs_properties_t*
filter::dynamic_mask::dynamic_mask_factory::get_properties2(filter::dynamic_mask::dynamic_mask_instance* data)
obs_properties_t* dynamic_mask::dynamic_mask_factory::get_properties2(dynamic_mask::dynamic_mask_instance* data)
{
obs_properties_t* props = obs_properties_create();
obs_property_t* p;
@ -446,7 +446,7 @@ obs_properties_t*
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_start(vargs, format);

View file

@ -40,92 +40,90 @@
#pragma warning(pop)
#endif
namespace filter {
namespace dynamic_mask {
enum class channel : int8_t { Invalid = -1, Red, Green, Blue, Alpha };
namespace filter::dynamic_mask {
enum class channel : int8_t { Invalid = -1, Red, Green, Blue, Alpha };
class dynamic_mask_instance : public obs::source_instance {
std::map<std::tuple<channel, channel, std::string>, std::string> _translation_map;
class dynamic_mask_instance : public obs::source_instance {
std::map<std::tuple<channel, channel, std::string>, std::string> _translation_map;
gs::effect _effect;
gs::effect _effect;
bool _have_filter_texture;
std::shared_ptr<gs::rendertarget> _filter_rt;
std::shared_ptr<gs::texture> _filter_texture;
bool _have_filter_texture;
std::shared_ptr<gs::rendertarget> _filter_rt;
std::shared_ptr<gs::texture> _filter_texture;
bool _have_input_texture;
std::shared_ptr<obs::deprecated_source> _input;
std::shared_ptr<gfx::source_texture> _input_capture;
std::shared_ptr<gs::texture> _input_texture;
bool _have_input_texture;
std::shared_ptr<obs::deprecated_source> _input;
std::shared_ptr<gfx::source_texture> _input_capture;
std::shared_ptr<gs::texture> _input_texture;
bool _have_final_texture;
std::shared_ptr<gs::rendertarget> _final_rt;
std::shared_ptr<gs::texture> _final_texture;
bool _have_final_texture;
std::shared_ptr<gs::rendertarget> _final_rt;
std::shared_ptr<gs::texture> _final_texture;
struct channel_data {
float_t value = 0.0;
float_t scale = 1.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);
struct channel_data {
float_t value = 0.0;
float_t scale = 1.0;
vec4 values = {0};
};
std::map<channel, channel_data> _channels;
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;
struct _precalc {
vec4 base;
vec4 scale;
matrix4 matrix;
} _precalc;
public: // Singleton
static void initialize()
{
factory_instance = std::make_shared<filter::dynamic_mask::dynamic_mask_factory>();
}
public:
dynamic_mask_instance(obs_data_t* data, obs_source_t* self);
virtual ~dynamic_mask_instance();
static void finalize()
{
factory_instance.reset();
}
virtual void update(obs_data_t* settings) override;
virtual void load(obs_data_t* settings) override;
virtual void save(obs_data_t* settings) override;
static std::shared_ptr<dynamic_mask_factory> get()
{
return factory_instance;
}
void input_renamed(obs::deprecated_source* src, std::string old_name, std::string new_name);
private:
std::list<std::string> _translation_cache;
static bool modified(void* self, obs_properties_t* properties, obs_property_t* property,
obs_data_t* settings) noexcept;
public:
dynamic_mask_factory();
virtual ~dynamic_mask_factory() override;
void video_tick(float _time);
void video_render(gs_effect_t* effect);
};
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, ...);
};
} // namespace dynamic_mask
} // namespace filter
static std::shared_ptr<dynamic_mask_factory> get()
{
return factory_instance;
}
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

View file

@ -65,10 +65,11 @@
#define ST_SDF_SCALE "Filter.SDFEffects.SDF.Scale"
#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 =
nullptr;
using namespace filter;
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(),
_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),
@ -100,14 +101,14 @@ filter::sdf_effects::sdf_effects_instance::sdf_effects_instance(obs_data_t* sett
for (auto& kv : load_arr) {
char* path = obs_module_file(kv.first);
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;
}
try {
kv.second = gs::effect::create(path);
} catch (const std::exception& ex) {
P_LOG_ERROR(LOG_PREFIX "Failed to load _effect '%s' (located at '%s') with error(s): %s", kv.first,
path, ex.what());
LOG_ERROR(LOG_PREFIX "Failed to load _effect '%s' (located at '%s') with error(s): %s", kv.first, path,
ex.what());
}
bfree(path);
}
@ -116,9 +117,9 @@ filter::sdf_effects::sdf_effects_instance::sdf_effects_instance(obs_data_t* sett
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 =
@ -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);
}
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);
}
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 height = 1;
@ -279,7 +280,7 @@ void filter::sdf_effects::sdf_effects_instance::video_tick(float)
_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* 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.type = OBS_SOURCE_TYPE_FILTER;
@ -518,14 +519,14 @@ filter::sdf_effects::sdf_effects_factory::sdf_effects_factory()
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);
}
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_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);
return true;
} 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 (...) {
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
@ -594,9 +595,9 @@ try {
obs_property_set_visible(obs_properties_get(props, ST_SHADOW_OUTER_ALPHA), v);
return true;
} 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 (...) {
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
@ -608,9 +609,9 @@ try {
obs_property_set_visible(obs_properties_get(props, ST_GLOW_INNER_SHARPNESS), v);
return true;
} 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 (...) {
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
@ -622,9 +623,9 @@ try {
obs_property_set_visible(obs_properties_get(props, ST_GLOW_OUTER_SHARPNESS), v);
return true;
} 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 (...) {
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
@ -637,9 +638,9 @@ try {
obs_property_set_visible(obs_properties_get(props, ST_OUTLINE_SHARPNESS), v);
return true;
} 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 (...) {
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
@ -649,13 +650,12 @@ try {
obs_property_set_visible(obs_properties_get(props, ST_SDF_THRESHOLD), show_advanced);
return true;
} 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 (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
}
obs_properties_t*
filter::sdf_effects::sdf_effects_factory::get_properties2(filter::sdf_effects::sdf_effects_instance* data)
obs_properties_t* sdf_effects::sdf_effects_factory::get_properties2(sdf_effects::sdf_effects_instance* data)
{
obs_properties_t* props = obs_properties_create();
obs_property_t* p = nullptr;

View file

@ -37,103 +37,101 @@
#pragma warning(pop)
#endif
namespace filter {
namespace sdf_effects {
class sdf_effects_instance : public obs::source_instance {
gs::effect _sdf_producer_effect;
gs::effect _sdf_consumer_effect;
namespace filter::sdf_effects {
class sdf_effects_instance : public obs::source_instance {
gs::effect _sdf_producer_effect;
gs::effect _sdf_consumer_effect;
// Input
std::shared_ptr<gs::rendertarget> _source_rt;
std::shared_ptr<gs::texture> _source_texture;
bool _source_rendered;
// Input
std::shared_ptr<gs::rendertarget> _source_rt;
std::shared_ptr<gs::texture> _source_texture;
bool _source_rendered;
// Distance Field
std::shared_ptr<gs::rendertarget> _sdf_write;
std::shared_ptr<gs::rendertarget> _sdf_read;
std::shared_ptr<gs::texture> _sdf_texture;
double_t _sdf_scale;
float_t _sdf_threshold;
// Distance Field
std::shared_ptr<gs::rendertarget> _sdf_write;
std::shared_ptr<gs::rendertarget> _sdf_read;
std::shared_ptr<gs::texture> _sdf_texture;
double_t _sdf_scale;
float_t _sdf_threshold;
// Effects
bool _output_rendered;
std::shared_ptr<gs::texture> _output_texture;
std::shared_ptr<gs::rendertarget> _output_rt;
/// Inner Shadow
bool _inner_shadow;
vec4 _inner_shadow_color;
float_t _inner_shadow_range_min;
float_t _inner_shadow_range_max;
float_t _inner_shadow_offset_x;
float_t _inner_shadow_offset_y;
/// Outer Shadow
bool _outer_shadow;
vec4 _outer_shadow_color;
float_t _outer_shadow_range_min;
float_t _outer_shadow_range_max;
float_t _outer_shadow_offset_x;
float_t _outer_shadow_offset_y;
/// Inner Glow
bool _inner_glow;
vec4 _inner_glow_color;
float_t _inner_glow_width;
float_t _inner_glow_sharpness;
float_t _inner_glow_sharpness_inv;
/// Outer Glow
bool _outer_glow;
vec4 _outer_glow_color;
float_t _outer_glow_width;
float_t _outer_glow_sharpness;
float_t _outer_glow_sharpness_inv;
/// Outline
bool _outline;
vec4 _outline_color;
float_t _outline_width;
float_t _outline_offset;
float_t _outline_sharpness;
float_t _outline_sharpness_inv;
// Effects
bool _output_rendered;
std::shared_ptr<gs::texture> _output_texture;
std::shared_ptr<gs::rendertarget> _output_rt;
/// Inner Shadow
bool _inner_shadow;
vec4 _inner_shadow_color;
float_t _inner_shadow_range_min;
float_t _inner_shadow_range_max;
float_t _inner_shadow_offset_x;
float_t _inner_shadow_offset_y;
/// Outer Shadow
bool _outer_shadow;
vec4 _outer_shadow_color;
float_t _outer_shadow_range_min;
float_t _outer_shadow_range_max;
float_t _outer_shadow_offset_x;
float_t _outer_shadow_offset_y;
/// Inner Glow
bool _inner_glow;
vec4 _inner_glow_color;
float_t _inner_glow_width;
float_t _inner_glow_sharpness;
float_t _inner_glow_sharpness_inv;
/// Outer Glow
bool _outer_glow;
vec4 _outer_glow_color;
float_t _outer_glow_width;
float_t _outer_glow_sharpness;
float_t _outer_glow_sharpness_inv;
/// Outline
bool _outline;
vec4 _outline_color;
float_t _outline_width;
float_t _outline_offset;
float_t _outline_sharpness;
float_t _outline_sharpness_inv;
public:
sdf_effects_instance(obs_data_t* settings, obs_source_t* self);
virtual ~sdf_effects_instance();
public:
sdf_effects_instance(obs_data_t* settings, obs_source_t* self);
virtual ~sdf_effects_instance();
virtual void update(obs_data_t* settings) override;
virtual void load(obs_data_t* settings) override;
virtual void update(obs_data_t* settings) override;
virtual void load(obs_data_t* settings) override;
virtual void video_tick(float) override;
virtual void video_render(gs_effect_t*) override;
};
virtual void video_tick(float) override;
virtual void video_render(gs_effect_t*) override;
};
class sdf_effects_factory : public obs::source_factory<filter::sdf_effects::sdf_effects_factory,
filter::sdf_effects::sdf_effects_instance> {
static std::shared_ptr<filter::sdf_effects::sdf_effects_factory> factory_instance;
class sdf_effects_factory : public obs::source_factory<filter::sdf_effects::sdf_effects_factory,
filter::sdf_effects::sdf_effects_instance> {
static std::shared_ptr<filter::sdf_effects::sdf_effects_factory> factory_instance;
public: // Singleton
static void initialize()
{
factory_instance = std::make_shared<filter::sdf_effects::sdf_effects_factory>();
}
public: // Singleton
static void initialize()
{
factory_instance = std::make_shared<filter::sdf_effects::sdf_effects_factory>();
}
static void finalize()
{
factory_instance.reset();
}
static void finalize()
{
factory_instance.reset();
}
static std::shared_ptr<sdf_effects_factory> get()
{
return factory_instance;
}
static std::shared_ptr<sdf_effects_factory> get()
{
return factory_instance;
}
public:
sdf_effects_factory();
virtual ~sdf_effects_factory();
public:
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
} // namespace filter::sdf_effects

View file

@ -64,6 +64,8 @@
#define ST_ROTATION_ORDER_ZYX "Filter.Transform.Rotation.Order.ZYX"
#define ST_MIPMAPPING "Filter.Transform.Mipmapping"
using namespace filter;
static const float farZ = 2097152.0f; // 2 pow 21
static const float nearZ = 1.0f / farZ;
@ -78,7 +80,7 @@ enum RotationOrder : int64_t {
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(),
_mipmap_generator(), _source_rendered(), _source_size(), _update_mesh(), _rotation_order(),
_camera_orthographic(), _camera_fov()
@ -99,7 +101,7 @@ filter::transform::transform_instance::transform_instance(obs_data_t* data, obs_
update(data);
}
filter::transform::transform_instance::~transform_instance()
transform::transform_instance::~transform_instance()
{
_shear.reset();
_scale.reset();
@ -111,12 +113,12 @@ filter::transform::transform_instance::~transform_instance()
_mipmap_texture.reset();
}
void filter::transform::transform_instance::load(obs_data_t* settings)
void transform::transform_instance::load(obs_data_t* settings)
{
update(settings);
}
void filter::transform::transform_instance::update(obs_data_t* settings)
void transform::transform_instance::update(obs_data_t* settings)
{
// Camera
_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;
}
void filter::transform::transform_instance::video_tick(float)
void transform::transform_instance::video_tick(float)
{
uint32_t width = 0;
uint32_t height = 0;
@ -263,7 +265,7 @@ void filter::transform::transform_instance::video_tick(float)
_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* 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.type = OBS_SOURCE_TYPE_FILTER;
@ -409,14 +411,14 @@ filter::transform::transform_factory::transform_factory()
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);
}
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_double(settings, ST_CAMERA_FIELDOFVIEW, 90.0);
@ -456,12 +458,12 @@ try {
return true;
} 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 (...) {
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();

View file

@ -27,81 +27,79 @@
#include "obs/obs-source-factory.hpp"
#include "plugin.hpp"
namespace filter {
namespace transform {
class transform_instance : public obs::source_instance {
// Cache
bool _cache_rendered;
std::shared_ptr<gs::rendertarget> _cache_rt;
std::shared_ptr<gs::texture> _cache_texture;
namespace filter::transform {
class transform_instance : public obs::source_instance {
// Cache
bool _cache_rendered;
std::shared_ptr<gs::rendertarget> _cache_rt;
std::shared_ptr<gs::texture> _cache_texture;
// Mip-mapping
bool _mipmap_enabled;
bool _mipmap_rendered;
double_t _mipmap_strength;
gs::mipmapper::generator _mipmap_generator;
gs::mipmapper _mipmapper;
std::shared_ptr<gs::texture> _mipmap_texture;
// Mip-mapping
bool _mipmap_enabled;
bool _mipmap_rendered;
double_t _mipmap_strength;
gs::mipmapper::generator _mipmap_generator;
gs::mipmapper _mipmapper;
std::shared_ptr<gs::texture> _mipmap_texture;
// Input
bool _source_rendered;
std::pair<uint32_t, uint32_t> _source_size;
std::shared_ptr<gs::rendertarget> _source_rt;
std::shared_ptr<gs::texture> _source_texture;
// Input
bool _source_rendered;
std::pair<uint32_t, uint32_t> _source_size;
std::shared_ptr<gs::rendertarget> _source_rt;
std::shared_ptr<gs::texture> _source_texture;
// Mesh
bool _update_mesh;
std::shared_ptr<gs::vertex_buffer> _vertex_buffer;
uint32_t _rotation_order;
std::unique_ptr<util::vec3a> _position;
std::unique_ptr<util::vec3a> _rotation;
std::unique_ptr<util::vec3a> _scale;
std::unique_ptr<util::vec3a> _shear;
// Mesh
bool _update_mesh;
std::shared_ptr<gs::vertex_buffer> _vertex_buffer;
uint32_t _rotation_order;
std::unique_ptr<util::vec3a> _position;
std::unique_ptr<util::vec3a> _rotation;
std::unique_ptr<util::vec3a> _scale;
std::unique_ptr<util::vec3a> _shear;
// Camera
bool _camera_orthographic;
float_t _camera_fov;
// Camera
bool _camera_orthographic;
float_t _camera_fov;
public:
transform_instance(obs_data_t*, obs_source_t*);
virtual ~transform_instance() override;
public:
transform_instance(obs_data_t*, obs_source_t*);
virtual ~transform_instance() override;
virtual void load(obs_data_t* settings) override;
virtual void update(obs_data_t*) override;
virtual void load(obs_data_t* settings) override;
virtual void update(obs_data_t*) override;
virtual void video_tick(float) override;
virtual void video_render(gs_effect_t*) override;
};
virtual void video_tick(float) override;
virtual void video_render(gs_effect_t*) override;
};
class transform_factory
: public obs::source_factory<filter::transform::transform_factory, filter::transform::transform_instance> {
static std::shared_ptr<filter::transform::transform_factory> factory_instance;
class transform_factory
: public obs::source_factory<filter::transform::transform_factory, filter::transform::transform_instance> {
static std::shared_ptr<filter::transform::transform_factory> factory_instance;
public: // Singleton
static void initialize()
{
factory_instance = std::make_shared<filter::transform::transform_factory>();
}
public: // Singleton
static void initialize()
{
factory_instance = std::make_shared<filter::transform::transform_factory>();
}
static void finalize()
{
factory_instance.reset();
}
static void finalize()
{
factory_instance.reset();
}
static std::shared_ptr<transform_factory> get()
{
return factory_instance;
}
static std::shared_ptr<transform_factory> get()
{
return factory_instance;
}
public:
transform_factory();
virtual ~transform_factory() override;
public:
transform_factory();
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;
};
} // namespace transform
} // namespace filter
virtual obs_properties_t* get_properties2(filter::transform::transform_instance* data) override;
};
} // namespace filter::transform

View file

@ -43,7 +43,7 @@ gfx::blur::box_linear_data::box_linear_data()
_effect = gs::effect::create(file);
bfree(file);
} catch (...) {
P_LOG_ERROR("<gfx::blur::box_linear> Failed to load _effect.");
LOG_ERROR("<gfx::blur::box_linear> Failed to load _effect.");
}
}

View file

@ -43,7 +43,7 @@ gfx::blur::box_data::box_data()
_effect = gs::effect::create(file);
bfree(file);
} catch (...) {
P_LOG_ERROR("<gfx::blur::box> Failed to load _effect.");
LOG_ERROR("<gfx::blur::box> Failed to load _effect.");
}
}

View file

@ -59,7 +59,7 @@ gfx::blur::dual_filtering_data::dual_filtering_data()
_effect = gs::effect::create(file);
bfree(file);
} catch (...) {
P_LOG_ERROR("<gfx::blur::box_linear> Failed to load _effect.");
LOG_ERROR("<gfx::blur::box_linear> Failed to load _effect.");
}
}

View file

@ -131,12 +131,12 @@ gfx::shader::basic_parameter::basic_parameter(gs::effect_parameter param, std::s
load_parameter_data(annoev, entry.data);
}
} else {
P_LOG_WARNING("[%s] Parameter enumeration entry '%s' is of invalid type, must be string.",
get_name().c_str(), string_buffer);
LOG_WARNING("[%s] Parameter enumeration entry '%s' is of invalid type, must be string.",
get_name().c_str(), string_buffer);
}
}
} 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;
}
}

View file

@ -65,7 +65,7 @@ try {
return false;
} 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;
}
@ -165,7 +165,7 @@ try {
return true;
} 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;
} catch (...) {
return false;

View file

@ -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());
}
} catch (...) {
P_LOG_ERROR("Failed to render mipmap layer.");
LOG_ERROR("Failed to render mipmap layer.");
}
#if defined(WIN32) || defined(WIN64)

View file

@ -19,6 +19,7 @@
#include "gs-sampler.hpp"
#include <stdexcept>
#include "utility.hpp"
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)
{
_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()

View file

@ -17,8 +17,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef STREAMEFFECTS_SOURCE_FACTORY_HPP
#define STREAMEFFECTS_SOURCE_FACTORY_HPP
#ifndef STREAMFX_SOURCE_FACTORY_HPP
#define STREAMFX_SOURCE_FACTORY_HPP
#pragma once
#include <stdexcept>
@ -183,10 +183,10 @@ namespace obs {
return reinterpret_cast<_factory*>(type_data)->get_name();
return nullptr;
} 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;
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
return nullptr;
}
@ -194,10 +194,10 @@ namespace obs {
try {
return reinterpret_cast<_factory*>(obs_source_get_type_data(source))->create(settings, source);
} 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;
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
return nullptr;
}
@ -206,9 +206,9 @@ namespace obs {
if (type_data)
reinterpret_cast<_factory*>(type_data)->get_defaults2(settings);
} 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 (...) {
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
@ -217,10 +217,10 @@ namespace obs {
return reinterpret_cast<_factory*>(type_data)->get_properties2(reinterpret_cast<_instance*>(data));
return nullptr;
} 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;
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
return nullptr;
}
@ -230,9 +230,9 @@ namespace obs {
if (data)
delete reinterpret_cast<_instance*>(data);
} 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 (...) {
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
@ -241,10 +241,10 @@ namespace obs {
return reinterpret_cast<_instance*>(data)->get_width();
return 0;
} 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;
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
return 0;
}
@ -254,10 +254,10 @@ namespace obs {
return reinterpret_cast<_instance*>(data)->get_height();
return 0;
} 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;
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
return 0;
}
@ -266,9 +266,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->update(settings);
} 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 (...) {
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
@ -276,9 +276,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->activate();
} 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 (...) {
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
@ -286,9 +286,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->deactivate();
} 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 (...) {
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
@ -296,9 +296,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->show();
} 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 (...) {
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
@ -306,9 +306,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->hide();
} 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 (...) {
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
@ -316,9 +316,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->video_tick(seconds);
} 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 (...) {
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
@ -326,9 +326,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->video_render(effect);
} 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 (...) {
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
@ -337,10 +337,10 @@ namespace obs {
return reinterpret_cast<_instance*>(data)->filter_video(frame);
return frame;
} 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;
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
return frame;
}
@ -350,10 +350,10 @@ namespace obs {
return reinterpret_cast<_instance*>(data)->filter_audio(frame);
return frame;
} 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;
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
return frame;
}
@ -362,9 +362,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->enum_active_sources(enum_callback, param);
} 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 (...) {
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
@ -372,9 +372,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->save(settings);
} 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 (...) {
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
@ -382,9 +382,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->load(settings);
} 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 (...) {
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,
@ -393,9 +393,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->mouse_click(event, type, mouse_up, click_count);
} 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 (...) {
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
@ -403,9 +403,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->mouse_move(event, mouse_leave);
} 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 (...) {
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
@ -413,9 +413,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->mouse_wheel(event, x_delta, y_delta);
} 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 (...) {
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
@ -423,9 +423,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->focus(focus);
} 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 (...) {
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
@ -433,9 +433,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->key_click(event, key_up);
} 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 (...) {
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
@ -443,9 +443,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->filter_remove(source);
} 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 (...) {
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,
@ -456,10 +456,10 @@ namespace obs {
sample_rate);
return false;
} 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;
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
return false;
}
@ -468,9 +468,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->enum_all_sources(enum_callback, param);
} 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 (...) {
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
@ -478,9 +478,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->transition_start();
} 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 (...) {
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
@ -488,9 +488,9 @@ namespace obs {
if (data)
reinterpret_cast<_instance*>(data)->transition_stop();
} 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 (...) {
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,
@ -500,10 +500,10 @@ namespace obs {
return reinterpret_cast<_instance*>(data)->audio_mix(ts_out, audio_output, channels, sample_rate);
return false;
} 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;
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
return false;
}

View file

@ -47,7 +47,7 @@ try {
self->_source_map.insert({std::string(name), weak});
} 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
@ -75,7 +75,7 @@ try {
obs_weak_source_release(found->second);
self->_source_map.erase(found);
} 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
@ -109,7 +109,7 @@ try {
self->_source_map.insert({new_name, found->second});
self->_source_map.erase(found);
} 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()

View file

@ -39,9 +39,9 @@ try {
}
self->events.destroy(self);
} 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 (...) {
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
@ -52,9 +52,9 @@ try {
}
self->events.remove(self);
} 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 (...) {
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
@ -65,9 +65,9 @@ try {
}
self->events.save(self);
} 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 (...) {
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
@ -78,9 +78,9 @@ try {
}
self->events.load(self);
} 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 (...) {
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
@ -91,9 +91,9 @@ try {
}
self->events.activate(self);
} 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 (...) {
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
@ -104,9 +104,9 @@ try {
}
self->events.deactivate(self);
} 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 (...) {
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
@ -117,9 +117,9 @@ try {
}
self->events.show(self);
} 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 (...) {
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
@ -130,9 +130,9 @@ try {
}
self->events.hide(self);
} 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 (...) {
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
@ -149,9 +149,9 @@ try {
self->events.enable(self, enabled);
} 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 (...) {
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
@ -168,9 +168,9 @@ try {
self->events.push_to_mute_changed(self, enabled);
} 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 (...) {
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
@ -187,9 +187,9 @@ try {
self->events.push_to_mute_delay(self, delay);
} 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 (...) {
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
@ -206,9 +206,9 @@ try {
self->events.push_to_talk_changed(self, enabled);
} 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 (...) {
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
@ -225,9 +225,9 @@ try {
self->events.push_to_talk_delay(self, delay);
} 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 (...) {
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
@ -249,9 +249,9 @@ try {
self->events.rename(self, std::string(new_name ? new_name : ""), std::string(prev_name ? prev_name : ""));
} 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 (...) {
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
@ -262,9 +262,9 @@ try {
}
self->events.update_properties(self);
} 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 (...) {
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
@ -281,9 +281,9 @@ try {
self->events.update_flags(self, flags);
} 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 (...) {
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
@ -300,9 +300,9 @@ try {
self->events.mute(self, muted);
} 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 (...) {
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
@ -321,9 +321,9 @@ try {
calldata_set_float(calldata, "volume", volume);
} 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 (...) {
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
@ -342,9 +342,9 @@ try {
calldata_set_int(calldata, "offset", mixers);
} 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 (...) {
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
@ -363,9 +363,9 @@ try {
calldata_set_int(calldata, "mixers", mixers);
} 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 (...) {
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
@ -377,9 +377,9 @@ try {
self->events.audio_data(self, audio, muted);
} 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 (...) {
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
@ -396,9 +396,9 @@ try {
self->events.filter_add(self, filter);
} 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 (...) {
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
@ -415,9 +415,9 @@ try {
self->events.filter_remove(self, filter);
} 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 (...) {
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
@ -428,9 +428,9 @@ try {
}
self->events.reorder_filters(self);
} 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 (...) {
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
@ -441,9 +441,9 @@ try {
}
self->events.transition_start(self);
} 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 (...) {
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
@ -454,9 +454,9 @@ try {
}
self->events.transition_video_stop(self);
} 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 (...) {
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
@ -467,9 +467,9 @@ try {
}
self->events.transition_stop(self);
} 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 (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
}
obs::deprecated_source::~deprecated_source()

View file

@ -45,7 +45,7 @@ try {
scs_searchdata& sd = reinterpret_cast<scs_searchdata&>(*reinterpret_cast<scs_searchdata*>(searchdata));
scs_contains(sd, child);
} 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
@ -54,7 +54,7 @@ try {
obs_source_t* source = obs_sceneitem_get_source(item);
return scs_contains(sd, source);
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
return false;
}

View file

@ -19,25 +19,33 @@
#include "plugin.hpp"
#include <stdexcept>
#include "obs/obs-source-tracker.hpp"
//#include "encoders/ffmpeg-encoder.hpp"
#include "filters/filter-blur.hpp"
#include "filters/filter-color-grade.hpp"
#include "filters/filter-displacement.hpp"
#include "filters/filter-dynamic-mask.hpp"
#include "filters/filter-sdf-effects.hpp"
//#include "filters/filter-shader.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-shader.hpp"
MODULE_EXPORT bool obs_module_load(void)
try {
P_LOG_INFO("Loading Version %s", STREAMEFFECTS_VERSION_STRING);
LOG_INFO("Loading Version %s", STREAMFX_VERSION_STRING);
// Initialize Source Tracker
obs::source_tracker::initialize();
// Initialize Filters
// Encoders
//encoder::ffmpeg::ffmpeg_manager::initialize();
// Filters
filter::blur::blur_factory::initialize();
filter::color_grade::color_grade_factory::initialize();
filter::displacement::displacement_factory::initialize();
@ -46,25 +54,29 @@ try {
//filter::shader::shader_factory::initialize();
filter::transform::transform_factory::initialize();
// Initialize Sources
// Sources
source::mirror::mirror_factory::initialize();
source::shader::shader_factory::initialize();
// Transitions
return true;
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
return false;
}
MODULE_EXPORT void obs_module_unload(void)
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::shader::shader_factory::finalize();
// Clean up Filters
// Filters
filter::blur::blur_factory::finalize();
filter::color_grade::color_grade_factory::finalize();
filter::displacement::displacement_factory::finalize();
@ -73,10 +85,13 @@ try {
//filter::shader::shader_factory::finalize();
filter::transform::transform_factory::finalize();
// Clean up Source Tracker
// Encoders
//encoder::ffmpeg::ffmpeg_manager::finalize();
// Finalize Source Tracker
obs::source_tracker::finalize();
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
}
#ifdef _WIN32

View file

@ -33,16 +33,16 @@
#endif
// Logging
#define P_LOG(level, ...) blog(level, "[" PLUGIN_NAME "] " __VA_ARGS__)
#define P_LOG_ERROR(...) P_LOG(LOG_ERROR, __VA_ARGS__)
#define P_LOG_WARNING(...) P_LOG(LOG_WARNING, __VA_ARGS__)
#define P_LOG_INFO(...) P_LOG(LOG_INFO, __VA_ARGS__)
#define P_LOG_DEBUG(...) P_LOG(LOG_DEBUG, __VA_ARGS__)
#define LOG_(level, ...) blog(level, "[" PLUGIN_NAME "] " __VA_ARGS__)
#define LOG_ERROR(...) LOG_(LOG_ERROR, __VA_ARGS__)
#define LOG_WARNING(...) LOG_(LOG_WARNING, __VA_ARGS__)
#define LOG_INFO(...) LOG_(LOG_INFO, __VA_ARGS__)
#define LOG_DEBUG(...) LOG_(LOG_DEBUG, __VA_ARGS__)
#ifndef __FUNCTION_NAME__
#ifdef WIN32 //WINDOWS
#ifdef WIN32 // WINDOWS
#define __FUNCTION_NAME__ __FUNCTION__
#else //*NIX
#else // *NIX
#define __FUNCTION_NAME__ __func__
#endif
#endif

View file

@ -63,7 +63,9 @@
#define ST_SCALING_BOUNDS_FILLHEIGHT ST_SCALING ".Bounds.FillHeight"
#define ST_SCALING_ALIGNMENT ST_SCALING ".Alignment"
void source::mirror::mirror_instance::release()
using namespace source;
void mirror::mirror_instance::release()
{
_source_item.reset();
if (_source) {
@ -74,7 +76,7 @@ void source::mirror::mirror_instance::release()
_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;
@ -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); });
// 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)
_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(),
_audio_kill_thread(), _audio_have_output(), _rescale_enabled(), _rescale_width(), _rescale_height(),
_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
/// 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);
}
source::mirror::mirror_instance::~mirror_instance()
mirror::mirror_instance::~mirror_instance()
{
release();
@ -142,12 +144,12 @@ source::mirror::mirror_instance::~mirror_instance()
_scene.reset();
}
uint32_t source::mirror::mirror_instance::get_width()
uint32_t mirror::mirror_instance::get_width()
{
return _source_size.first;
}
uint32_t source::mirror::mirror_instance::get_height()
uint32_t mirror::mirror_instance::get_height()
{
return _source_size.second;
}
@ -160,15 +162,15 @@ static void convert_config(obs_data_t* data)
case 0:
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");
case STREAMEFFECTS_VERSION:
case STREAMFX_VERSION:
break;
}
obs_data_set_int(data, S_VERSION, STREAMEFFECTS_VERSION);
obs_data_set_string(data, S_COMMIT, STREAMEFFECTS_COMMIT);
obs_data_set_int(data, S_VERSION, STREAMFX_VERSION);
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);
@ -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);
}
void source::mirror::mirror_instance::save(obs_data_t* data)
void mirror::mirror_instance::save(obs_data_t* data)
{
if (_source) {
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 (_rescale_keep_orig_size || !_rescale_enabled) {
@ -272,7 +274,7 @@ void source::mirror::mirror_instance::video_tick(float time)
_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)
return;
@ -314,7 +316,7 @@ void source::mirror::mirror_instance::video_render(gs_effect_t* effect)
GS_DEBUG_MARKER_END();
}
void source::mirror::mirror_instance::audio_output_cb() noexcept
void mirror::mirror_instance::audio_output_cb() noexcept
try {
std::unique_lock<std::mutex> ulock(this->_audio_lock_outputter);
@ -347,12 +349,12 @@ try {
}
}
} 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 (...) {
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) {
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) {
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);
}
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) {
return;
@ -443,9 +445,9 @@ void source::mirror::mirror_instance::on_audio_data(obs::deprecated_source*, con
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.type = OBS_SOURCE_TYPE_INPUT;
@ -454,14 +456,14 @@ source::mirror::mirror_factory::mirror_factory()
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);
}
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_bool(data, ST_SOURCE_AUDIO, false);
@ -532,14 +534,14 @@ try {
return false;
} 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;
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
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_property_t* p = nullptr;

View file

@ -41,108 +41,105 @@
#pragma warning(pop)
#endif
namespace source {
namespace mirror {
struct mirror_audio_data {
obs_source_audio audio = {};
std::vector<std::vector<float_t>> data;
};
namespace source::mirror {
struct mirror_audio_data {
obs_source_audio audio = {};
std::vector<std::vector<float_t>> data;
};
class mirror_instance : public obs::source_instance {
// Source
std::shared_ptr<obs::deprecated_source> _source;
std::string _source_name;
class mirror_instance : public obs::source_instance {
// Source
std::shared_ptr<obs::deprecated_source> _source;
std::string _source_name;
// Cached Data
std::pair<uint32_t, uint32_t> _source_size;
// Cached Data
std::pair<uint32_t, uint32_t> _source_size;
// Audio
bool _audio_enabled;
speaker_layout _audio_layout;
std::condition_variable _audio_notify;
std::thread _audio_thread;
bool _audio_kill_thread;
bool _audio_have_output;
std::mutex _audio_lock_outputter;
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_free_queue;
// Audio
bool _audio_enabled;
speaker_layout _audio_layout;
std::condition_variable _audio_notify;
std::thread _audio_thread;
bool _audio_kill_thread;
bool _audio_have_output;
std::mutex _audio_lock_outputter;
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_free_queue;
// Scaling
bool _rescale_enabled;
uint32_t _rescale_width;
uint32_t _rescale_height;
bool _rescale_keep_orig_size;
obs_scale_type _rescale_type;
obs_bounds_type _rescale_bounds;
uint32_t _rescale_alignment;
// Scaling
bool _rescale_enabled;
uint32_t _rescale_width;
uint32_t _rescale_height;
bool _rescale_keep_orig_size;
obs_scale_type _rescale_type;
obs_bounds_type _rescale_bounds;
uint32_t _rescale_alignment;
// Caching
bool _cache_enabled;
bool _cache_rendered;
std::shared_ptr<gfx::source_texture> _cache_renderer;
std::shared_ptr<gs::texture> _cache_texture;
// Caching
bool _cache_enabled;
bool _cache_rendered;
std::shared_ptr<gfx::source_texture> _cache_renderer;
std::shared_ptr<gs::texture> _cache_texture;
// Scene
std::shared_ptr<obs_source_t> _scene;
std::shared_ptr<obs_sceneitem_t> _source_item;
// Scene
std::shared_ptr<obs_source_t> _scene;
std::shared_ptr<obs_sceneitem_t> _source_item;
private:
void release();
void acquire(std::string source_name);
private:
void release();
void acquire(std::string source_name);
public:
mirror_instance(obs_data_t* settings, obs_source_t* self);
virtual ~mirror_instance();
public:
mirror_instance(obs_data_t* settings, obs_source_t* self);
virtual ~mirror_instance();
virtual uint32_t get_width() override;
virtual uint32_t get_height() override;
virtual uint32_t get_width() override;
virtual uint32_t get_height() override;
virtual void update(obs_data_t*) override;
virtual void load(obs_data_t*) override;
virtual void save(obs_data_t*) override;
virtual void update(obs_data_t*) override;
virtual void load(obs_data_t*) override;
virtual void save(obs_data_t*) override;
virtual void video_tick(float) override;
virtual void video_render(gs_effect_t*) override;
virtual void video_tick(float) override;
virtual void video_render(gs_effect_t*) 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_active_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_audio_data(obs::deprecated_source* source, const audio_data* audio, bool muted);
};
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);
};
class mirror_factory
: public obs::source_factory<source::mirror::mirror_factory, source::mirror::mirror_instance> {
static std::shared_ptr<source::mirror::mirror_factory> factory_instance;
class mirror_factory : public obs::source_factory<source::mirror::mirror_factory, source::mirror::mirror_instance> {
static std::shared_ptr<source::mirror::mirror_factory> factory_instance;
public: // Singleton
static void initialize()
{
factory_instance = std::make_shared<source::mirror::mirror_factory>();
}
public: // Singleton
static void initialize()
{
factory_instance = std::make_shared<source::mirror::mirror_factory>();
}
static void finalize()
{
factory_instance.reset();
}
static void finalize()
{
factory_instance.reset();
}
static std::shared_ptr<mirror_factory> get()
{
return factory_instance;
}
static std::shared_ptr<mirror_factory> get()
{
return factory_instance;
}
public:
mirror_factory();
virtual ~mirror_factory() override;
public:
mirror_factory();
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;
};
} // namespace mirror
}; // namespace source
virtual obs_properties_t* get_properties2(source::mirror::mirror_instance* data) override;
};
} // namespace source::mirror

View file

@ -24,7 +24,9 @@
#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)
{
_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);
}
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();
}
uint32_t source::shader::shader_instance::get_height()
uint32_t shader::shader_instance::get_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);
}
void source::shader::shader_instance::load(obs_data_t* data)
void shader::shader_instance::load(obs_data_t* 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);
}
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)) {
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;
}
void source::shader::shader_instance::video_render(gs_effect_t* effect)
void shader::shader_instance::video_render(gs_effect_t* effect)
{
if (!_fx) {
return;
@ -86,9 +88,9 @@ void source::shader::shader_instance::video_render(gs_effect_t* effect)
_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.type = OBS_SOURCE_TYPE_INPUT;
@ -97,16 +99,16 @@ source::shader::shader_factory::shader_factory()
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);
}
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();
obs_properties_set_param(pr, data, nullptr);

View file

@ -28,58 +28,55 @@ extern "C" {
#include <obs.h>
}
namespace source {
namespace shader {
class shader_instance : public obs::source_instance {
std::shared_ptr<gfx::shader::shader> _fx;
namespace source::shader {
class shader_instance : public obs::source_instance {
std::shared_ptr<gfx::shader::shader> _fx;
bool _is_main;
bool _is_main;
public:
shader_instance(obs_data_t* data, obs_source_t* self);
virtual ~shader_instance();
public:
shader_instance(obs_data_t* data, obs_source_t* self);
virtual ~shader_instance();
virtual uint32_t get_width() override;
virtual uint32_t get_height() override;
virtual uint32_t get_width() 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 update(obs_data_t* data) override;
virtual void load(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_render(gs_effect_t* effect) override;
};
virtual void video_tick(float_t sec_since_last) override;
virtual void video_render(gs_effect_t* effect) override;
};
class shader_factory
: public obs::source_factory<source::shader::shader_factory, source::shader::shader_instance> {
static std::shared_ptr<source::shader::shader_factory> factory_instance;
class shader_factory : public obs::source_factory<source::shader::shader_factory, source::shader::shader_instance> {
static std::shared_ptr<source::shader::shader_factory> factory_instance;
public: // Singleton
static void initialize()
{
factory_instance = std::make_shared<source::shader::shader_factory>();
}
public: // Singleton
static void initialize()
{
factory_instance = std::make_shared<source::shader::shader_factory>();
}
static void finalize()
{
factory_instance.reset();
}
static void finalize()
{
factory_instance.reset();
}
static std::shared_ptr<shader_factory> get()
{
return factory_instance;
}
static std::shared_ptr<shader_factory> get()
{
return factory_instance;
}
public:
shader_factory();
virtual ~shader_factory();
public:
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;
};
} // namespace shader
} // namespace source
virtual obs_properties_t* get_properties2(source::shader::shader_instance* data) override;
};
} // namespace source::shader

View file

@ -37,6 +37,7 @@
#define S_ADVANCED "Advanced"
#define S_STATE_DEFAULT "State.Default"
#define S_STATE_DISABLED "State.Disabled"
#define S_STATE_ENABLED "State.Enabled"
#define S_STATE_MANUAL "State.Manual"

View file

@ -27,6 +27,7 @@
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4201)
#pragma warning(disable : 5039)
#endif
#include <obs.h>
#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;
}

View file

@ -76,4 +76,51 @@ namespace util {
{
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