mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-08-10 00:52:16 +00:00
refactor(video): move encoder declarations to header (#2185)
This commit is contained in:
157
src/video.cpp
157
src/video.cpp
@@ -14,7 +14,6 @@ extern "C" {
|
||||
#include <libavutil/mastering_display_metadata.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include <libavutil/pixdesc.h>
|
||||
#include <libswscale/swscale.h>
|
||||
}
|
||||
|
||||
#include "cbs.h"
|
||||
@@ -51,12 +50,6 @@ namespace video {
|
||||
av_buffer_unref(&ref);
|
||||
}
|
||||
|
||||
using avcodec_ctx_t = util::safe_ptr<AVCodecContext, free_ctx>;
|
||||
using avcodec_frame_t = util::safe_ptr<AVFrame, free_frame>;
|
||||
using avcodec_buffer_t = util::safe_ptr<AVBufferRef, free_buffer>;
|
||||
using sws_t = util::safe_ptr<SwsContext, sws_freeContext>;
|
||||
using img_event_t = std::shared_ptr<safe::event_t<std::shared_ptr<platf::img_t>>>;
|
||||
|
||||
namespace nv {
|
||||
|
||||
enum class profile_h264_e : int {
|
||||
@@ -87,11 +80,6 @@ namespace video {
|
||||
};
|
||||
} // namespace qsv
|
||||
|
||||
platf::mem_type_e
|
||||
map_base_dev_type(AVHWDeviceType type);
|
||||
platf::pix_fmt_e
|
||||
map_pix_fmt(AVPixelFormat fmt);
|
||||
|
||||
util::Either<avcodec_buffer_t, int>
|
||||
dxgi_init_avcodec_hardware_input_buffer(platf::avcodec_encode_device_t *);
|
||||
util::Either<avcodec_buffer_t, int>
|
||||
@@ -288,137 +276,6 @@ namespace video {
|
||||
ALWAYS_REPROBE = 1 << 9, // This is an encoder of last resort and we want to aggressively probe for a better one
|
||||
};
|
||||
|
||||
struct encoder_platform_formats_t {
|
||||
virtual ~encoder_platform_formats_t() = default;
|
||||
platf::mem_type_e dev_type;
|
||||
platf::pix_fmt_e pix_fmt_8bit, pix_fmt_10bit;
|
||||
};
|
||||
|
||||
struct encoder_platform_formats_avcodec: encoder_platform_formats_t {
|
||||
using init_buffer_function_t = std::function<util::Either<avcodec_buffer_t, int>(platf::avcodec_encode_device_t *)>;
|
||||
|
||||
encoder_platform_formats_avcodec(
|
||||
const AVHWDeviceType &avcodec_base_dev_type,
|
||||
const AVHWDeviceType &avcodec_derived_dev_type,
|
||||
const AVPixelFormat &avcodec_dev_pix_fmt,
|
||||
const AVPixelFormat &avcodec_pix_fmt_8bit,
|
||||
const AVPixelFormat &avcodec_pix_fmt_10bit,
|
||||
const init_buffer_function_t &init_avcodec_hardware_input_buffer_function):
|
||||
avcodec_base_dev_type { avcodec_base_dev_type },
|
||||
avcodec_derived_dev_type { avcodec_derived_dev_type },
|
||||
avcodec_dev_pix_fmt { avcodec_dev_pix_fmt },
|
||||
avcodec_pix_fmt_8bit { avcodec_pix_fmt_8bit },
|
||||
avcodec_pix_fmt_10bit { avcodec_pix_fmt_10bit },
|
||||
init_avcodec_hardware_input_buffer { init_avcodec_hardware_input_buffer_function } {
|
||||
dev_type = map_base_dev_type(avcodec_base_dev_type);
|
||||
pix_fmt_8bit = map_pix_fmt(avcodec_pix_fmt_8bit);
|
||||
pix_fmt_10bit = map_pix_fmt(avcodec_pix_fmt_10bit);
|
||||
}
|
||||
|
||||
AVHWDeviceType avcodec_base_dev_type, avcodec_derived_dev_type;
|
||||
AVPixelFormat avcodec_dev_pix_fmt;
|
||||
AVPixelFormat avcodec_pix_fmt_8bit, avcodec_pix_fmt_10bit;
|
||||
|
||||
init_buffer_function_t init_avcodec_hardware_input_buffer;
|
||||
};
|
||||
|
||||
struct encoder_platform_formats_nvenc: encoder_platform_formats_t {
|
||||
encoder_platform_formats_nvenc(
|
||||
const platf::mem_type_e &dev_type,
|
||||
const platf::pix_fmt_e &pix_fmt_8bit,
|
||||
const platf::pix_fmt_e &pix_fmt_10bit) {
|
||||
encoder_platform_formats_t::dev_type = dev_type;
|
||||
encoder_platform_formats_t::pix_fmt_8bit = pix_fmt_8bit;
|
||||
encoder_platform_formats_t::pix_fmt_10bit = pix_fmt_10bit;
|
||||
}
|
||||
};
|
||||
|
||||
struct encoder_t {
|
||||
std::string_view name;
|
||||
enum flag_e {
|
||||
PASSED, // Is supported
|
||||
REF_FRAMES_RESTRICT, // Set maximum reference frames
|
||||
CBR, // Some encoders don't support CBR, if not supported --> attempt constant quantatication parameter instead
|
||||
DYNAMIC_RANGE, // hdr
|
||||
VUI_PARAMETERS, // AMD encoder with VAAPI doesn't add VUI parameters to SPS
|
||||
MAX_FLAGS
|
||||
};
|
||||
|
||||
static std::string_view
|
||||
from_flag(flag_e flag) {
|
||||
#define _CONVERT(x) \
|
||||
case flag_e::x: \
|
||||
return #x##sv
|
||||
switch (flag) {
|
||||
_CONVERT(PASSED);
|
||||
_CONVERT(REF_FRAMES_RESTRICT);
|
||||
_CONVERT(CBR);
|
||||
_CONVERT(DYNAMIC_RANGE);
|
||||
_CONVERT(VUI_PARAMETERS);
|
||||
_CONVERT(MAX_FLAGS);
|
||||
}
|
||||
#undef _CONVERT
|
||||
|
||||
return "unknown"sv;
|
||||
}
|
||||
|
||||
struct option_t {
|
||||
KITTY_DEFAULT_CONSTR_MOVE(option_t)
|
||||
option_t(const option_t &) = default;
|
||||
|
||||
std::string name;
|
||||
std::variant<int, int *, std::optional<int> *, std::function<int()>, std::string, std::string *> value;
|
||||
|
||||
option_t(std::string &&name, decltype(value) &&value):
|
||||
name { std::move(name) }, value { std::move(value) } {}
|
||||
};
|
||||
|
||||
const std::unique_ptr<const encoder_platform_formats_t> platform_formats;
|
||||
|
||||
struct {
|
||||
std::vector<option_t> common_options;
|
||||
std::vector<option_t> sdr_options;
|
||||
std::vector<option_t> hdr_options;
|
||||
std::vector<option_t> fallback_options;
|
||||
|
||||
// QP option to set in the case that CBR/VBR is not supported
|
||||
// by the encoder. If CBR/VBR is guaranteed to be supported,
|
||||
// don't specify this option to avoid wasteful encoder probing.
|
||||
std::optional<option_t> qp;
|
||||
|
||||
std::string name;
|
||||
std::bitset<MAX_FLAGS> capabilities;
|
||||
|
||||
bool
|
||||
operator[](flag_e flag) const {
|
||||
return capabilities[(std::size_t) flag];
|
||||
}
|
||||
|
||||
std::bitset<MAX_FLAGS>::reference
|
||||
operator[](flag_e flag) {
|
||||
return capabilities[(std::size_t) flag];
|
||||
}
|
||||
} av1, hevc, h264;
|
||||
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct encode_session_t {
|
||||
virtual ~encode_session_t() = default;
|
||||
|
||||
virtual int
|
||||
convert(platf::img_t &img) = 0;
|
||||
|
||||
virtual void
|
||||
request_idr_frame() = 0;
|
||||
|
||||
virtual void
|
||||
request_normal_frame() = 0;
|
||||
|
||||
virtual void
|
||||
invalidate_ref_frames(int64_t first_frame, int64_t last_frame) = 0;
|
||||
};
|
||||
|
||||
class avcodec_encode_session_t: public encode_session_t {
|
||||
public:
|
||||
avcodec_encode_session_t() = default;
|
||||
@@ -586,7 +443,7 @@ namespace video {
|
||||
auto capture_thread_sync = safe::make_shared<capture_thread_sync_ctx_t>(start_capture_sync, end_capture_sync);
|
||||
|
||||
#ifdef _WIN32
|
||||
static encoder_t nvenc {
|
||||
encoder_t nvenc {
|
||||
"nvenc"sv,
|
||||
std::make_unique<encoder_platform_formats_nvenc>(
|
||||
platf::mem_type_e::dxgi,
|
||||
@@ -630,7 +487,7 @@ namespace video {
|
||||
PARALLEL_ENCODING | REF_FRAMES_INVALIDATION // flags
|
||||
};
|
||||
#elif !defined(__APPLE__)
|
||||
static encoder_t nvenc {
|
||||
encoder_t nvenc {
|
||||
"nvenc"sv,
|
||||
std::make_unique<encoder_platform_formats_avcodec>(
|
||||
#ifdef _WIN32
|
||||
@@ -718,7 +575,7 @@ namespace video {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
static encoder_t quicksync {
|
||||
encoder_t quicksync {
|
||||
"quicksync"sv,
|
||||
std::make_unique<encoder_platform_formats_avcodec>(
|
||||
AV_HWDEVICE_TYPE_D3D11VA, AV_HWDEVICE_TYPE_QSV,
|
||||
@@ -799,7 +656,7 @@ namespace video {
|
||||
PARALLEL_ENCODING | CBR_WITH_VBR | RELAXED_COMPLIANCE | NO_RC_BUF_LIMIT
|
||||
};
|
||||
|
||||
static encoder_t amdvce {
|
||||
encoder_t amdvce {
|
||||
"amdvce"sv,
|
||||
std::make_unique<encoder_platform_formats_avcodec>(
|
||||
AV_HWDEVICE_TYPE_D3D11VA, AV_HWDEVICE_TYPE_NONE,
|
||||
@@ -871,7 +728,7 @@ namespace video {
|
||||
};
|
||||
#endif
|
||||
|
||||
static encoder_t software {
|
||||
encoder_t software {
|
||||
"software"sv,
|
||||
std::make_unique<encoder_platform_formats_avcodec>(
|
||||
AV_HWDEVICE_TYPE_NONE, AV_HWDEVICE_TYPE_NONE,
|
||||
@@ -936,7 +793,7 @@ namespace video {
|
||||
};
|
||||
|
||||
#ifdef __linux__
|
||||
static encoder_t vaapi {
|
||||
encoder_t vaapi {
|
||||
"vaapi"sv,
|
||||
std::make_unique<encoder_platform_formats_avcodec>(
|
||||
AV_HWDEVICE_TYPE_VAAPI, AV_HWDEVICE_TYPE_NONE,
|
||||
@@ -1004,7 +861,7 @@ namespace video {
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
static encoder_t videotoolbox {
|
||||
encoder_t videotoolbox {
|
||||
"videotoolbox"sv,
|
||||
std::make_unique<encoder_platform_formats_avcodec>(
|
||||
AV_HWDEVICE_TYPE_VIDEOTOOLBOX, AV_HWDEVICE_TYPE_NONE,
|
||||
|
||||
172
src/video.h
172
src/video.h
@@ -11,11 +11,181 @@
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libswscale/swscale.h>
|
||||
}
|
||||
|
||||
struct AVPacket;
|
||||
namespace video {
|
||||
|
||||
platf::mem_type_e
|
||||
map_base_dev_type(AVHWDeviceType type);
|
||||
platf::pix_fmt_e
|
||||
map_pix_fmt(AVPixelFormat fmt);
|
||||
|
||||
void
|
||||
free_ctx(AVCodecContext *ctx);
|
||||
void
|
||||
free_frame(AVFrame *frame);
|
||||
void
|
||||
free_buffer(AVBufferRef *ref);
|
||||
|
||||
using avcodec_ctx_t = util::safe_ptr<AVCodecContext, free_ctx>;
|
||||
using avcodec_frame_t = util::safe_ptr<AVFrame, free_frame>;
|
||||
using avcodec_buffer_t = util::safe_ptr<AVBufferRef, free_buffer>;
|
||||
using sws_t = util::safe_ptr<SwsContext, sws_freeContext>;
|
||||
using img_event_t = std::shared_ptr<safe::event_t<std::shared_ptr<platf::img_t>>>;
|
||||
|
||||
struct encoder_platform_formats_t {
|
||||
virtual ~encoder_platform_formats_t() = default;
|
||||
platf::mem_type_e dev_type;
|
||||
platf::pix_fmt_e pix_fmt_8bit, pix_fmt_10bit;
|
||||
};
|
||||
|
||||
struct encoder_platform_formats_avcodec: encoder_platform_formats_t {
|
||||
using init_buffer_function_t = std::function<util::Either<avcodec_buffer_t, int>(platf::avcodec_encode_device_t *)>;
|
||||
|
||||
encoder_platform_formats_avcodec(
|
||||
const AVHWDeviceType &avcodec_base_dev_type,
|
||||
const AVHWDeviceType &avcodec_derived_dev_type,
|
||||
const AVPixelFormat &avcodec_dev_pix_fmt,
|
||||
const AVPixelFormat &avcodec_pix_fmt_8bit,
|
||||
const AVPixelFormat &avcodec_pix_fmt_10bit,
|
||||
const init_buffer_function_t &init_avcodec_hardware_input_buffer_function):
|
||||
avcodec_base_dev_type { avcodec_base_dev_type },
|
||||
avcodec_derived_dev_type { avcodec_derived_dev_type },
|
||||
avcodec_dev_pix_fmt { avcodec_dev_pix_fmt },
|
||||
avcodec_pix_fmt_8bit { avcodec_pix_fmt_8bit },
|
||||
avcodec_pix_fmt_10bit { avcodec_pix_fmt_10bit },
|
||||
init_avcodec_hardware_input_buffer { init_avcodec_hardware_input_buffer_function } {
|
||||
dev_type = map_base_dev_type(avcodec_base_dev_type);
|
||||
pix_fmt_8bit = map_pix_fmt(avcodec_pix_fmt_8bit);
|
||||
pix_fmt_10bit = map_pix_fmt(avcodec_pix_fmt_10bit);
|
||||
}
|
||||
|
||||
AVHWDeviceType avcodec_base_dev_type, avcodec_derived_dev_type;
|
||||
AVPixelFormat avcodec_dev_pix_fmt;
|
||||
AVPixelFormat avcodec_pix_fmt_8bit, avcodec_pix_fmt_10bit;
|
||||
|
||||
init_buffer_function_t init_avcodec_hardware_input_buffer;
|
||||
};
|
||||
|
||||
struct encoder_platform_formats_nvenc: encoder_platform_formats_t {
|
||||
encoder_platform_formats_nvenc(
|
||||
const platf::mem_type_e &dev_type,
|
||||
const platf::pix_fmt_e &pix_fmt_8bit,
|
||||
const platf::pix_fmt_e &pix_fmt_10bit) {
|
||||
encoder_platform_formats_t::dev_type = dev_type;
|
||||
encoder_platform_formats_t::pix_fmt_8bit = pix_fmt_8bit;
|
||||
encoder_platform_formats_t::pix_fmt_10bit = pix_fmt_10bit;
|
||||
}
|
||||
};
|
||||
|
||||
struct encoder_t {
|
||||
std::string_view name;
|
||||
enum flag_e {
|
||||
PASSED, // Is supported
|
||||
REF_FRAMES_RESTRICT, // Set maximum reference frames
|
||||
CBR, // Some encoders don't support CBR, if not supported --> attempt constant quantatication parameter instead
|
||||
DYNAMIC_RANGE, // hdr
|
||||
VUI_PARAMETERS, // AMD encoder with VAAPI doesn't add VUI parameters to SPS
|
||||
MAX_FLAGS
|
||||
};
|
||||
|
||||
static std::string_view
|
||||
from_flag(flag_e flag) {
|
||||
#define _CONVERT(x) \
|
||||
case flag_e::x: \
|
||||
std::string_view(#x)
|
||||
switch (flag) {
|
||||
_CONVERT(PASSED);
|
||||
_CONVERT(REF_FRAMES_RESTRICT);
|
||||
_CONVERT(CBR);
|
||||
_CONVERT(DYNAMIC_RANGE);
|
||||
_CONVERT(VUI_PARAMETERS);
|
||||
_CONVERT(MAX_FLAGS);
|
||||
}
|
||||
#undef _CONVERT
|
||||
|
||||
return { "unknown" };
|
||||
}
|
||||
|
||||
struct option_t {
|
||||
KITTY_DEFAULT_CONSTR_MOVE(option_t)
|
||||
option_t(const option_t &) = default;
|
||||
|
||||
std::string name;
|
||||
std::variant<int, int *, std::optional<int> *, std::function<int()>, std::string, std::string *> value;
|
||||
|
||||
option_t(std::string &&name, decltype(value) &&value):
|
||||
name { std::move(name) }, value { std::move(value) } {}
|
||||
};
|
||||
|
||||
const std::unique_ptr<const encoder_platform_formats_t> platform_formats;
|
||||
|
||||
struct codec_t {
|
||||
std::vector<option_t> common_options;
|
||||
std::vector<option_t> sdr_options;
|
||||
std::vector<option_t> hdr_options;
|
||||
std::vector<option_t> fallback_options;
|
||||
|
||||
// QP option to set in the case that CBR/VBR is not supported
|
||||
// by the encoder. If CBR/VBR is guaranteed to be supported,
|
||||
// don't specify this option to avoid wasteful encoder probing.
|
||||
std::optional<option_t> qp;
|
||||
|
||||
std::string name;
|
||||
std::bitset<MAX_FLAGS> capabilities;
|
||||
|
||||
bool
|
||||
operator[](flag_e flag) const {
|
||||
return capabilities[(std::size_t) flag];
|
||||
}
|
||||
|
||||
std::bitset<MAX_FLAGS>::reference
|
||||
operator[](flag_e flag) {
|
||||
return capabilities[(std::size_t) flag];
|
||||
}
|
||||
} av1, hevc, h264;
|
||||
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct encode_session_t {
|
||||
virtual ~encode_session_t() = default;
|
||||
|
||||
virtual int
|
||||
convert(platf::img_t &img) = 0;
|
||||
|
||||
virtual void
|
||||
request_idr_frame() = 0;
|
||||
|
||||
virtual void
|
||||
request_normal_frame() = 0;
|
||||
|
||||
virtual void
|
||||
invalidate_ref_frames(int64_t first_frame, int64_t last_frame) = 0;
|
||||
};
|
||||
|
||||
// encoders
|
||||
extern encoder_t software;
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
extern encoder_t nvenc; // available for windows and linux
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
extern encoder_t amdvce;
|
||||
extern encoder_t quicksync;
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
extern encoder_t vaapi;
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
extern encoder_t videotoolbox;
|
||||
#endif
|
||||
|
||||
struct packet_raw_t {
|
||||
virtual ~packet_raw_t() = default;
|
||||
|
||||
@@ -154,6 +324,8 @@ namespace video {
|
||||
config_t config,
|
||||
void *channel_data);
|
||||
|
||||
bool
|
||||
validate_encoder(encoder_t &encoder, bool expect_failure);
|
||||
int
|
||||
probe_encoders();
|
||||
} // namespace video
|
||||
|
||||
Reference in New Issue
Block a user