Implement AV1 support

This commit is contained in:
Cameron Gutman 2023-08-13 15:51:48 -05:00
commit 69e720b44b
10 changed files with 389 additions and 44 deletions

View file

@ -130,12 +130,19 @@ namespace config {
namespace amd {
#ifdef __APPLE__
// values accurate as of 27/12/2022, but aren't strictly necessary for MacOS build
#define AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_SPEED 100
#define AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_QUALITY 30
#define AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_BALANCED 70
#define AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED 10
#define AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY 0
#define AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_BALANCED 5
#define AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED 1
#define AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY 2
#define AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED 0
#define AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CONSTANT_QP 0
#define AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR 3
#define AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR 2
#define AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR 1
#define AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP 0
#define AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR 3
#define AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR 2
@ -144,6 +151,10 @@ namespace config {
#define AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR 1
#define AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR 2
#define AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR 3
#define AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING 0
#define AMF_VIDEO_ENCODER_AV1_USAGE_LOW_LATENCY 1
#define AMF_VIDEO_ENCODER_AV1_USAGE_ULTRA_LOW_LATENCY 2
#define AMF_VIDEO_ENCODER_AV1_USAGE_WEBCAM 3
#define AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING 0
#define AMF_VIDEO_ENCODER_HEVC_USAGE_ULTRA_LOW_LATENCY 1
#define AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY 2
@ -156,10 +167,17 @@ namespace config {
#define AMF_VIDEO_ENCODER_CABAC 1
#define AMF_VIDEO_ENCODER_CALV 2
#else
#include <AMF/components/VideoEncoderAV1.h>
#include <AMF/components/VideoEncoderHEVC.h>
#include <AMF/components/VideoEncoderVCE.h>
#endif
enum class quality_av1_e : int {
speed = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_SPEED,
quality = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_QUALITY,
balanced = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_BALANCED
};
enum class quality_hevc_e : int {
speed = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED,
quality = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY,
@ -172,6 +190,13 @@ namespace config {
balanced = AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED
};
enum class rc_av1_e : int {
cqp = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CONSTANT_QP,
vbr_latency = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR,
vbr_peak = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR,
cbr = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR
};
enum class rc_hevc_e : int {
cqp = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP,
vbr_latency = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR,
@ -186,6 +211,13 @@ namespace config {
cbr = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR
};
enum class usage_av1_e : int {
transcoding = AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING,
webcam = AMF_VIDEO_ENCODER_AV1_USAGE_WEBCAM,
lowlatency = AMF_VIDEO_ENCODER_AV1_USAGE_LOW_LATENCY,
ultralowlatency = AMF_VIDEO_ENCODER_AV1_USAGE_ULTRA_LOW_LATENCY
};
enum class usage_hevc_e : int {
transcoding = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING,
webcam = AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM,
@ -206,10 +238,11 @@ namespace config {
cavlc = AMF_VIDEO_ENCODER_CALV
};
template <class T>
std::optional<int>
quality_from_view(const std::string_view &quality_type, int codec) {
quality_from_view(const std::string_view &quality_type) {
#define _CONVERT_(x) \
if (quality_type == #x##sv) return codec == 0 ? (int) quality_hevc_e::x : (int) quality_h264_e::x
if (quality_type == #x##sv) return (int) T::x
_CONVERT_(quality);
_CONVERT_(speed);
_CONVERT_(balanced);
@ -217,10 +250,11 @@ namespace config {
return std::nullopt;
}
template <class T>
std::optional<int>
rc_from_view(const std::string_view &rc, int codec) {
rc_from_view(const std::string_view &rc) {
#define _CONVERT_(x) \
if (rc == #x##sv) return codec == 0 ? (int) rc_hevc_e::x : (int) rc_h264_e::x
if (rc == #x##sv) return (int) T::x
_CONVERT_(cqp);
_CONVERT_(vbr_latency);
_CONVERT_(vbr_peak);
@ -229,10 +263,11 @@ namespace config {
return std::nullopt;
}
template <class T>
std::optional<int>
usage_from_view(const std::string_view &rc, int codec) {
usage_from_view(const std::string_view &rc) {
#define _CONVERT_(x) \
if (rc == #x##sv) return codec == 0 ? (int) usage_hevc_e::x : (int) usage_h264_e::x
if (rc == #x##sv) return (int) T::x
_CONVERT_(transcoding);
_CONVERT_(webcam);
_CONVERT_(lowlatency);
@ -333,15 +368,36 @@ namespace config {
} // namespace vt
namespace sw {
int
svtav1_preset_from_view(const std::string_view &preset) {
#define _CONVERT_(x, y) \
if (preset == #x##sv) return y
_CONVERT_(veryslow, 1);
_CONVERT_(slower, 2);
_CONVERT_(slow, 4);
_CONVERT_(medium, 5);
_CONVERT_(fast, 7);
_CONVERT_(faster, 9);
_CONVERT_(veryfast, 10);
_CONVERT_(superfast, 11);
_CONVERT_(ultrafast, 12);
#undef _CONVERT_
return 11; // Default to superfast
}
} // namespace sw
video_t video {
28, // qp
0, // hevc_mode
0, // av1_mode
1, // min_threads
{
"superfast"s, // preset
"zerolatency"s, // tune
11, // superfast
}, // software
{
@ -359,10 +415,13 @@ namespace config {
{
(int) amd::quality_h264_e::balanced, // quality (h264)
(int) amd::quality_hevc_e::balanced, // quality (hevc)
(int) amd::quality_av1_e::balanced, // quality (av1)
(int) amd::rc_h264_e::vbr_latency, // rate control (h264)
(int) amd::rc_hevc_e::vbr_latency, // rate control (hevc)
(int) amd::rc_av1_e::vbr_latency, // rate control (av1)
(int) amd::usage_h264_e::ultralowlatency, // usage (h264)
(int) amd::usage_hevc_e::ultralowlatency, // usage (hevc)
(int) amd::usage_av1_e::ultralowlatency, // usage (av1)
0, // preanalysis
1, // vbaq
(int) amd::coder_e::_auto, // coder
@ -924,7 +983,11 @@ namespace config {
int_f(vars, "qp", video.qp);
int_f(vars, "min_threads", video.min_threads);
int_between_f(vars, "hevc_mode", video.hevc_mode, { 0, 3 });
int_between_f(vars, "av1_mode", video.av1_mode, { 0, 3 });
string_f(vars, "sw_preset", video.sw.sw_preset);
if (!video.sw.sw_preset.empty()) {
video.sw.svtav1_preset = sw::svtav1_preset_from_view(video.sw.sw_preset);
}
string_f(vars, "sw_tune", video.sw.sw_tune);
int_f(vars, "nv_preset", video.nv.nv_preset, nv::preset_from_view);
int_f(vars, "nv_tune", video.nv.nv_tune, nv::tune_from_view);
@ -937,23 +1000,26 @@ namespace config {
std::string quality;
string_f(vars, "amd_quality", quality);
if (!quality.empty()) {
video.amd.amd_quality_h264 = amd::quality_from_view(quality, 1);
video.amd.amd_quality_hevc = amd::quality_from_view(quality, 0);
video.amd.amd_quality_h264 = amd::quality_from_view<amd::quality_h264_e>(quality);
video.amd.amd_quality_hevc = amd::quality_from_view<amd::quality_hevc_e>(quality);
video.amd.amd_quality_av1 = amd::quality_from_view<amd::quality_av1_e>(quality);
}
std::string rc;
string_f(vars, "amd_rc", rc);
int_f(vars, "amd_coder", video.amd.amd_coder, amd::coder_from_view);
if (!rc.empty()) {
video.amd.amd_rc_h264 = amd::rc_from_view(rc, 1);
video.amd.amd_rc_hevc = amd::rc_from_view(rc, 0);
video.amd.amd_rc_h264 = amd::rc_from_view<amd::rc_h264_e>(rc);
video.amd.amd_rc_hevc = amd::rc_from_view<amd::rc_hevc_e>(rc);
video.amd.amd_rc_av1 = amd::rc_from_view<amd::rc_av1_e>(rc);
}
std::string usage;
string_f(vars, "amd_usage", usage);
if (!usage.empty()) {
video.amd.amd_usage_h264 = amd::usage_from_view(rc, 1);
video.amd.amd_usage_hevc = amd::usage_from_view(rc, 0);
video.amd.amd_usage_h264 = amd::usage_from_view<amd::usage_h264_e>(rc);
video.amd.amd_usage_hevc = amd::usage_from_view<amd::usage_hevc_e>(rc);
video.amd.amd_usage_av1 = amd::usage_from_view<amd::usage_av1_e>(rc);
}
bool_f(vars, "amd_preanalysis", (bool &) video.amd.amd_preanalysis);