Merge pull request #7809 from obsproject/amf-av1-rebased

Add Hardware AMD AV1 Encoder
This commit is contained in:
Jim
2022-11-19 15:52:16 -08:00
committed by GitHub
20 changed files with 1033 additions and 99 deletions

View File

@@ -950,6 +950,7 @@ Basic.Settings.Output.Simple.Encoder.Software="Software (x264)"
Basic.Settings.Output.Simple.Encoder.Hardware.QSV.H264="Hardware (QSV, H.264)"
Basic.Settings.Output.Simple.Encoder.Hardware.AMD.H264="Hardware (AMD, H.264)"
Basic.Settings.Output.Simple.Encoder.Hardware.AMD.HEVC="Hardware (AMD, HEVC)"
Basic.Settings.Output.Simple.Encoder.Hardware.AMD.AV1="Hardware (AMD, AV1)"
Basic.Settings.Output.Simple.Encoder.Hardware.NVENC.H264="Hardware (NVENC, H.264)"
Basic.Settings.Output.Simple.Encoder.Hardware.NVENC.AV1="Hardware (NVENC, AV1)"
Basic.Settings.Output.Simple.Encoder.Hardware.NVENC.HEVC="Hardware (NVENC, HEVC)"

View File

@@ -377,6 +377,8 @@ const char *get_simple_output_encoder(const char *encoder)
} else if (strcmp(encoder, SIMPLE_ENCODER_AMD_HEVC) == 0) {
return "h265_texture_amf";
#endif
} else if (strcmp(encoder, SIMPLE_ENCODER_AMD_AV1) == 0) {
return "av1_texture_amf";
} else if (strcmp(encoder, SIMPLE_ENCODER_NVENC) == 0) {
return EncoderAvailable("jim_nvenc") ? "jim_nvenc"
: "ffmpeg_nvenc";
@@ -549,6 +551,9 @@ void SimpleOutput::Update()
presetType = "NVENCPreset2";
#endif
} else if (strcmp(encoder, SIMPLE_ENCODER_AMD_AV1) == 0) {
presetType = "AMDAV1Preset";
} else if (strcmp(encoder, SIMPLE_ENCODER_NVENC_AV1) == 0) {
presetType = "NVENCPreset2";

View File

@@ -829,6 +829,7 @@ void OBSBasic::CheckForSimpleModeX264Fallback()
bool nve_hevc_supported = false;
bool apple_hevc_supported = false;
#endif
bool amd_av1_supported = false;
bool apple_supported = false;
bool changed = false;
size_t idx = 0;
@@ -847,6 +848,8 @@ void OBSBasic::CheckForSimpleModeX264Fallback()
else if (strcmp(id, "ffmpeg_hevc_nvenc") == 0)
nve_hevc_supported = true;
#endif
else if (strcmp(id, "av1_texture_amf") == 0)
amd_av1_supported = true;
else if (strcmp(id,
"com.apple.videotoolbox.videoencoder.ave.avc") ==
0)
@@ -898,6 +901,12 @@ void OBSBasic::CheckForSimpleModeX264Fallback()
name = SIMPLE_ENCODER_X264;
return false;
}
} else if (strcmp(name, SIMPLE_ENCODER_AMD_AV1) == 0) {
if (!amd_av1_supported) {
changed = true;
name = SIMPLE_ENCODER_X264;
return false;
}
} else if (strcmp(name, SIMPLE_ENCODER_APPLE_H264) == 0) {
if (!apple_supported) {
changed = true;

View File

@@ -70,6 +70,7 @@ class OBSBasicStats;
#define SIMPLE_ENCODER_NVENC_HEVC "nvenc_hevc"
#define SIMPLE_ENCODER_AMD "amd"
#define SIMPLE_ENCODER_AMD_HEVC "amd_hevc"
#define SIMPLE_ENCODER_AMD_AV1 "amd_av1"
#define SIMPLE_ENCODER_APPLE_H264 "apple_h264"
#define SIMPLE_ENCODER_APPLE_HEVC "apple_hevc"

View File

@@ -1729,6 +1729,8 @@ void OBSBasicSettings::LoadSimpleOutputSettings()
"NVENCPreset2");
const char *amdPreset =
config_get_string(main->Config(), "SimpleOutput", "AMDPreset");
const char *amdAV1Preset = config_get_string(
main->Config(), "SimpleOutput", "AMDAV1Preset");
const char *custom = config_get_string(main->Config(), "SimpleOutput",
"x264Settings");
const char *recQual =
@@ -1748,6 +1750,7 @@ void OBSBasicSettings::LoadSimpleOutputSettings()
curQSVPreset = qsvPreset;
curNVENCPreset = nvPreset;
curAMDPreset = amdPreset;
curAMDAV1Preset = amdAV1Preset;
audioBitrate = FindClosestAvailableAACBitrate(audioBitrate);
@@ -3491,6 +3494,8 @@ void OBSBasicSettings::SaveOutputSettings()
#endif
else if (encoder == SIMPLE_ENCODER_AMD)
presetType = "AMDPreset";
else if (encoder == SIMPLE_ENCODER_AMD_AV1)
presetType = "AMDAV1Preset";
else if (encoder == SIMPLE_ENCODER_APPLE_H264
#ifdef ENABLE_HEVC
|| encoder == SIMPLE_ENCODER_APPLE_HEVC
@@ -4776,6 +4781,10 @@ void OBSBasicSettings::FillSimpleRecordingValues()
ui->simpleOutRecEncoder->addItem(
ENCODER_STR("Hardware.AMD.H264"),
QString(SIMPLE_ENCODER_AMD));
if (EncoderAvailable("av1_texture_amf"))
ui->simpleOutRecEncoder->addItem(
ENCODER_STR("Hardware.AMD.AV1"),
QString(SIMPLE_ENCODER_AMD_AV1));
if (EncoderAvailable("com.apple.videotoolbox.videoencoder.ave.avc")
#ifndef __aarch64__
&& os_get_emulation_status() == true
@@ -4892,6 +4901,15 @@ void OBSBasicSettings::SimpleStreamingEncoderChanged()
ui->simpleOutAdvanced->setVisible(false);
ui->simpleOutPreset->setVisible(false);
ui->simpleOutPresetLabel->setVisible(false);
} else if (encoder == SIMPLE_ENCODER_AMD_AV1) {
ui->simpleOutPreset->addItem("Speed", "speed");
ui->simpleOutPreset->addItem("Balanced", "balanced");
ui->simpleOutPreset->addItem("Quality", "quality");
ui->simpleOutPreset->addItem("High Quality", "highQuality");
defaultPreset = "balanced";
preset = curAMDAV1Preset;
} else {
#define PRESET_STR(val) \

View File

@@ -146,6 +146,7 @@ private:
QString curQSVPreset;
QString curNVENCPreset;
QString curAMDPreset;
QString curAMDAV1Preset;
QString curAdvStreamEncoder;
QString curAdvRecordEncoder;

View File

@@ -14,7 +14,7 @@ Lossless="Lossless"
Level="Level"
AMFOpts="AMF/FFmpeg Options"
AMFOpts.ToolTip="Use to specify custom AMF or FFmpeg options. For example, \"level=5.2 profile=main BPicturesPattern=3\""
AMFOpts.ToolTip="Use to specify custom AMF or FFmpeg options. For example, \"level=5.2 profile=main\". Check the AMF encoder docs for more details."
BFrames="Max B-frames"
@@ -48,6 +48,7 @@ NVENC.Multipass.fullres="Two Passes (Full Resolution)"
AMF.Preset.speed="Speed"
AMF.Preset.balanced="Balanced"
AMF.Preset.quality="Quality"
AMF.Preset.highQuality="High Quality"
FFmpegSource="Media Source"
LocalFile="Local File"

View File

@@ -414,6 +414,7 @@ typedef enum AMF_STREAM_CODEC_ID_ENUM // matched codecs from VideoDecoxcderU
AMF_STREAM_CODEC_ID_VP9 = 11, // AMFVideoDecoderHW_VP9
AMF_STREAM_CODEC_ID_VP9_10BIT = 12, // AMFVideoDecoderHW_VP9_10BIT
AMF_STREAM_CODEC_ID_AV1 = 13, // AMFVideoDecoderHW_AV1
AMF_STREAM_CODEC_ID_AV1_12BIT = 14, // AMFVideoDecoderHW_AV1_12BIT
} AMF_STREAM_CODEC_ID_ENUM;
// common stream properties

View File

@@ -43,6 +43,7 @@ namespace amf
class AMFCursorCapture : public AMFInterface
{
public:
AMF_DECLARE_IID(0x166efa1a, 0x19b8, 0x42f2, 0x86, 0x0f, 0x56, 0x69, 0xca, 0x7a, 0x85, 0x4c)
virtual AMF_RESULT AMF_STD_CALL AcquireCursor(amf::AMFSurface** pSurface) = 0;
virtual AMF_RESULT AMF_STD_CALL Reset() = 0;
};

View File

@@ -49,5 +49,6 @@
#define FFMPEG_MUXER_ENABLE_AUDIO L"EnableAudio" // bool (default = false)
#define FFMPEG_MUXER_CURRENT_TIME_INTERFACE L"CurrentTimeInterface"
#define FFMPEG_MUXER_VIDEO_ROTATION L"VideoRotation" // amf_int64 (0, 90, 180, 270, default = 0)
#define FFMPEG_MUXER_USAGE_IS_TRIM L"UsageIsTrim" // bool (default = false)
#endif //#ifndef AMF_FileMuxerFFMPEG_h

View File

@@ -44,6 +44,8 @@ enum AMF_HQ_SCALER_ALGORITHM_ENUM
AMF_HQ_SCALER_ALGORITHM_BILINEAR = 0,
AMF_HQ_SCALER_ALGORITHM_BICUBIC = 1,
AMF_HQ_SCALER_ALGORITHM_FSR = 2,
AMF_HQ_SCALER_ALGORITHM_POINT = 3,
AMF_HQ_SCALER_ALGORITHM_FSR1_1 = 4,
};
@@ -60,5 +62,6 @@ enum AMF_HQ_SCALER_ALGORITHM_ENUM
#define AMF_HQ_SCALER_FILL_COLOR L"FillColor" // AMFColor
#define AMF_HQ_SCALER_FROM_SRGB L"FromSRGB" // bool (default=true) Convert to SRGB.
#define AMF_HQ_SCALER_SHARPNESS L"HQScalerSharpness" // Float in the range of [0.0, 2.0]
#endif //#ifndef AMFHQScaler_h

View File

@@ -1,4 +1,4 @@
//
//
// Notice Regarding Standards. AMD does not provide a license or sublicense to
// any Intellectual Property Rights relating to any standards, including but not
// limited to any audio and/or video codec technologies such as MPEG-2, MPEG-4;
@@ -6,9 +6,9 @@
// (collectively, the "Media Technologies"). For clarity, you will pay any
// royalties due for such third party technologies, which may include the Media
// Technologies that are owed as a result of AMD providing the Software to you.
//
// MIT license
//
//
// MIT license
//
// Copyright (c) 2019 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -48,7 +48,7 @@ enum AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_ENUM
enum AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_ENUM
{
{
AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_LOW = 0,
AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_MEDIUM = 1,
AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_HIGH = 2
@@ -69,6 +69,26 @@ enum AMF_PA_CAQ_STRENGTH_ENUM
AMF_PA_CAQ_STRENGTH_HIGH = 2
};
// Perceptual adaptive quantization mode
enum AMF_PA_PAQ_MODE_ENUM
{
AMF_PA_PAQ_MODE_NONE = 0,
AMF_PA_PAQ_MODE_CAQ = 1
};
// Temporal adaptive quantization mode
enum AMF_PA_TAQ_MODE_ENUM
{
AMF_PA_TAQ_MODE_NONE = 0,
AMF_PA_TAQ_MODE_1 = 1,
AMF_PA_TAQ_MODE_2 = 2
};
enum AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_ENUM
{
AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_NONE = 0, //default
AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_AUTO = 1
};
// PA object properties
@@ -77,17 +97,19 @@ enum AMF_PA_CAQ_STRENGTH_ENUM
#define AMF_PA_SCENE_CHANGE_DETECTION_ENABLE L"PASceneChangeDetectionEnable" // bool (default : True) - Enable Scene Change Detection GPU algorithm
#define AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY L"PASceneChangeDetectionSensitivity" // AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_ENUM (default : Medium) - Scene Change Detection Sensitivity
#define AMF_PA_STATIC_SCENE_DETECTION_ENABLE L"PAStaticSceneDetectionEnable" // bool (default : True) - Enable Skip Detection GPU algorithm
#define AMF_PA_STATIC_SCENE_DETECTION_ENABLE L"PAStaticSceneDetectionEnable" // bool (default : False) - Enable Skip Detection GPU algorithm
#define AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY L"PAStaticSceneDetectionSensitivity" // AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_ENUM (default : High) - Allowable absolute difference between pixels (sample counts)
#define AMF_PA_FRAME_SAD_ENABLE L"PAFrameSadEnable" // bool (default : True) - Enable Frame SAD algorithm
#define AMF_PA_ACTIVITY_TYPE L"PAActivityType" // AMF_PA_ACTIVITY_TYPE_ENUM (default : Calculate on Y) - Block activity calculation mode
#define AMF_PA_LTR_ENABLE L"PALongTermReferenceEnable" // bool (default : True) - Enable Automatic Long Term Reference frame management
#define AMF_PA_LTR_ENABLE L"PALongTermReferenceEnable" // bool (default : False) - Enable Automatic Long Term Reference frame management
#define AMF_PA_LOOKAHEAD_BUFFER_DEPTH L"PALookAheadBufferDepth" // amf_uint64 (default : 0) Values: [0, MAX_LOOKAHEAD_DEPTH] - PA lookahead buffer size
#define AMF_PA_PAQ_MODE L"PAPerceptualAQMode" // AMF_PA_PAQ_MODE_ENUM (default : AMF_PA_PAQ_MODE_NONE) - Perceptual AQ mode
#define AMF_PA_TAQ_MODE L"PATemporalAQMode" // AMF_PA_TAQ_MODE_ENUM (default: AMF_PA_TAQ_MODE_NONE) - Temporal AQ mode
#define AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE L"PAHighMotionQualityBoostMode" // AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_ENUM (default: None) - High motion quality boost mode
///////////////////////////////////////////
// the following properties are available
// only through the Encoder - trying to
// the following properties are available
// only through the Encoder - trying to
// access/set them when PA is standalone
// will fail
@@ -107,4 +129,5 @@ enum AMF_PA_CAQ_STRENGTH_ENUM
#define AMF_PA_SCENE_CHANGE_DETECT L"PASceneChangeDetect" // bool - True/False - available if AMF_PA_SCENE_CHANGE_DETECTION_ENABLE was set to True
#define AMF_PA_STATIC_SCENE_DETECT L"PAStaticSceneDetect" // bool - True/False - available if AMF_PA_STATIC_SCENE_DETECTION_ENABLE was set to True
#endif //#ifndef AMFPreAnalysis_h

View File

@@ -0,0 +1,47 @@
//
// Notice Regarding Standards. AMD does not provide a license or sublicense to
// any Intellectual Property Rights relating to any standards, including but not
// limited to any audio and/or video codec technologies such as MPEG-2, MPEG-4;
// AVC/H.264; HEVC/H.265; AAC decode/FFMPEG; AAC encode/FFMPEG; VC-1; and MP3
// (collectively, the "Media Technologies"). For clarity, you will pay any
// royalties due for such third party technologies, which may include the Media
// Technologies that are owed as a result of AMD providing the Software to you.
//
// MIT license
//
// Copyright (c) 2021 Advanced Micro Devices, Inc. All rights reserved.
//
// 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.
//
#ifndef AMFVQEnhancer_h
#define AMFVQEnhancer_h
#pragma once
#define VE_FCR_DEFAULT_ATTENUATION 0.1
#define AMFVQEnhancer L"AMFVQEnhancer"
#define AMF_VIDEO_ENHANCER_ENGINE_TYPE L"AMF_VIDEI_ENHANCER_ENGINE_TYPE" // AMF_MEMORY_TYPE (DX11, DX12, OPENCL, VULKAN default : DX11)" - determines how the object is initialized and what kernels to use
#define AMF_VIDEO_ENHANCER_OUTPUT_SIZE L"AMF_VIDEO_ENHANCER_OUTPUT_SIZE" // AMFSize
#define AMF_VE_FCR_ATTENUATION L"AMF_VE_FCR_ATTENUATION" // Float in the range of [0.02, 0.4], default : 0.1
#define AMF_VE_FCR_RADIUS L"AMF_VE_FCR_RADIUS" // int in the range of [1, 4]
#endif //#ifndef AMFVQEnhancer_h

View File

@@ -53,6 +53,7 @@
#define AMFVideoDecoderHW_VP9 L"AMFVideoDecoderHW_VP9"
#define AMFVideoDecoderHW_VP9_10BIT L"AMFVideoDecoderHW_VP9_10BIT"
#define AMFVideoDecoderHW_AV1 L"AMFVideoDecoderHW_AV1"
#define AMFVideoDecoderHW_AV1_12BIT L"AMFVideoDecoderHW_AV1_12BIT"
enum AMF_VIDEO_DECODER_MODE_ENUM
{
@@ -108,6 +109,7 @@ enum AMF_TIMESTAMP_MODE_ENUM
#define AMF_VIDEO_DECODER_OUTPUT_COLOR_PRIMARIES L"OutputColorPrimaries" // amf_int64(AMF_COLOR_PRIMARIES_ENUM); default = AMF_COLOR_PRIMARIES_UNDEFINED, ISO/IEC 23001-8_2013 7.1 See ColorSpace.h for enum
#define AMF_VIDEO_DECODER_OUTPUT_HDR_METADATA L"OutHDRMetadata" // AMFBuffer containing AMFHDRMetadata; default NULL
#define AMF_VIDEO_DECODER_LOW_LATENCY L"LowLatencyDecode" // amf_bool; default = false; true = low latency decode, false = regular decode
#if defined(__ANDROID__)
#define AMF_VIDEO_DECODER_NATIVEWINDOW L"AndroidNativeWindow" // amf_int64; default = 0; pointer to native window
@@ -118,5 +120,4 @@ enum AMF_TIMESTAMP_MODE_ENUM
#define AMF_VIDEO_DECODER_NATIVEWINDOW L"AppleNativeWindow" // amf_int64; default = 0; pointer to native window
#endif //__APPLE__
#endif //#ifndef AMF_VideoDecoderUVD_h

View File

@@ -0,0 +1,292 @@
//
// Copyright (c) 2021-2022 Advanced Micro Devices, Inc. All rights reserved.
//
// 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.
//
//-------------------------------------------------------------------------------------------------
// VideoEncoderHW_AV1 interface declaration
//-------------------------------------------------------------------------------------------------
#ifndef AMF_VideoEncoderAV1_h
#define AMF_VideoEncoderAV1_h
#pragma once
#include "Component.h"
#include "ColorSpace.h"
#include "PreAnalysis.h"
#define AMFVideoEncoder_AV1 L"AMFVideoEncoderHW_AV1"
enum AMF_VIDEO_ENCODER_AV1_ENCODING_LATENCY_MODE_ENUM
{
AMF_VIDEO_ENCODER_AV1_ENCODING_LATENCY_MODE_NONE = 0, // No encoding latency requirement. Encoder will balance encoding time and power consumption.
AMF_VIDEO_ENCODER_AV1_ENCODING_LATENCY_MODE_POWER_SAVING_REAL_TIME = 1, // Try the best to finish encoding a frame within 1/framerate sec. This mode may cause more power consumption
AMF_VIDEO_ENCODER_AV1_ENCODING_LATENCY_MODE_REAL_TIME = 2, // Try the best to finish encoding a frame within 1/(2 x framerate) sec. This mode will cause more power consumption than POWER_SAVING_REAL_TIME
AMF_VIDEO_ENCODER_AV1_ENCODING_LATENCY_MODE_LOWEST_LATENCY = 3 // Encoding as fast as possible. This mode causes highest power consumption.
};
enum AMF_VIDEO_ENCODER_AV1_USAGE_ENUM
{
AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING = 0,
AMF_VIDEO_ENCODER_AV1_USAGE_LOW_LATENCY = 1
};
enum AMF_VIDEO_ENCODER_AV1_PROFILE_ENUM
{
AMF_VIDEO_ENCODER_AV1_PROFILE_MAIN = 1
};
enum AMF_VIDEO_ENCODER_AV1_LEVEL_ENUM
{
AMF_VIDEO_ENCODER_AV1_LEVEL_2_0 = 0,
AMF_VIDEO_ENCODER_AV1_LEVEL_2_1 = 1,
AMF_VIDEO_ENCODER_AV1_LEVEL_2_2 = 2,
AMF_VIDEO_ENCODER_AV1_LEVEL_2_3 = 3,
AMF_VIDEO_ENCODER_AV1_LEVEL_3_0 = 4,
AMF_VIDEO_ENCODER_AV1_LEVEL_3_1 = 5,
AMF_VIDEO_ENCODER_AV1_LEVEL_3_2 = 6,
AMF_VIDEO_ENCODER_AV1_LEVEL_3_3 = 7,
AMF_VIDEO_ENCODER_AV1_LEVEL_4_0 = 8,
AMF_VIDEO_ENCODER_AV1_LEVEL_4_1 = 9,
AMF_VIDEO_ENCODER_AV1_LEVEL_4_2 = 10,
AMF_VIDEO_ENCODER_AV1_LEVEL_4_3 = 11,
AMF_VIDEO_ENCODER_AV1_LEVEL_5_0 = 12,
AMF_VIDEO_ENCODER_AV1_LEVEL_5_1 = 13,
AMF_VIDEO_ENCODER_AV1_LEVEL_5_2 = 14,
AMF_VIDEO_ENCODER_AV1_LEVEL_5_3 = 15,
AMF_VIDEO_ENCODER_AV1_LEVEL_6_0 = 16,
AMF_VIDEO_ENCODER_AV1_LEVEL_6_1 = 17,
AMF_VIDEO_ENCODER_AV1_LEVEL_6_2 = 18,
AMF_VIDEO_ENCODER_AV1_LEVEL_6_3 = 19,
AMF_VIDEO_ENCODER_AV1_LEVEL_7_0 = 20,
AMF_VIDEO_ENCODER_AV1_LEVEL_7_1 = 21,
AMF_VIDEO_ENCODER_AV1_LEVEL_7_2 = 22,
AMF_VIDEO_ENCODER_AV1_LEVEL_7_3 = 23
};
enum AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_ENUM
{
AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_UNKNOWN = -1,
AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CONSTANT_QP = 0,
AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR = 1,
AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR = 2,
AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR = 3,
AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_QUALITY_VBR = 4,
AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_HIGH_QUALITY_VBR = 5,
AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_HIGH_QUALITY_CBR = 6
};
enum AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_ENUM
{
AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_ONLY = 1,
AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_1080P_CODED_1082 = 2,
AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_NO_RESTRICTIONS = 3
};
enum AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_ENUM
{
AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_NONE = 0,
AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_KEY = 1,
AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_INTRA_ONLY = 2,
AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_SWITCH = 3,
AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_SHOW_EXISTING = 4
};
enum AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_ENUM
{
AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_KEY = 0,
AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_INTRA_ONLY = 1,
AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_INTER = 2,
AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_SWITCH = 3,
AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_SHOW_EXISTING = 4
};
enum AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_ENUM
{
AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_HIGH_QUALITY = 0,
AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_QUALITY = 30,
AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_BALANCED = 70,
AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_SPEED = 100
};
enum AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_ENUM
{
AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_NONE = 0,
AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_GOP_ALIGNED = 1,
AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_KEY_FRAME_ALIGNED = 2
};
enum AMF_VIDEO_ENCODER_AV1_SWITCH_FRAME_INSERTION_MODE_ENUM
{
AMF_VIDEO_ENCODER_AV1_SWITCH_FRAME_INSERTION_MODE_NONE = 0,
AMF_VIDEO_ENCODER_AV1_SWITCH_FRAME_INSERTION_MODE_FIXED_INTERVAL = 1
};
enum AMF_VIDEO_ENCODER_AV1_CDEF_MODE_ENUM
{
AMF_VIDEO_ENCODER_AV1_CDEF_DISABLE = 0,
AMF_VIDEO_ENCODER_AV1_CDEF_ENABLE_DEFAULT = 1
};
enum AMF_VIDEO_ENCODER_AV1_CDF_FRAME_END_UPDATE_MODE_ENUM
{
AMF_VIDEO_ENCODER_AV1_CDF_FRAME_END_UPDATE_MODE_DISABLE = 0,
AMF_VIDEO_ENCODER_AV1_CDF_FRAME_END_UPDATE_MODE_ENABLE_DEFAULT = 1
};
enum AMF_VIDEO_ENCODER_AV1_AQ_MODE_ENUM
{
AMF_VIDEO_ENCODER_AV1_AQ_MODE_NONE = 0,
AMF_VIDEO_ENCODER_AV1_AQ_MODE_CAQ = 1 // Content adaptive quantization mode
};
enum AMF_VIDEO_ENCODER_AV1_INTRA_REFRESH_MODE_ENUM
{
AMF_VIDEO_ENCODER_AV1_INTRA_REFRESH_MODE__DISABLED = 0,
AMF_VIDEO_ENCODER_AV1_INTRA_REFRESH_MODE__GOP_ALIGNED = 1,
AMF_VIDEO_ENCODER_AV1_INTRA_REFRESH_MODE__CONTINUOUS = 2
};
// *** Static properties - can be set only before Init() ***
// Encoder Engine Settings
#define AMF_VIDEO_ENCODER_AV1_ENCODER_INSTANCE_INDEX L"Av1EncoderInstanceIndex" // amf_int64; default = 0; selected HW instance idx. The number of instances is queried by using AMF_VIDEO_ENCODER_AV1_CAP_NUM_OF_HW_INSTANCES
#define AMF_VIDEO_ENCODER_AV1_ENCODING_LATENCY_MODE L"Av1EncodingLatencyMode" // amf_int64(AMF_VIDEO_ENCODER_AV1_ENCODING_LATENCY_MODE_ENUM); default = depends on USAGE; The encoding latency mode.
#define AMF_VIDEO_ENCODER_AV1_QUERY_TIMEOUT L"Av1QueryTimeout" // amf_int64; default = 0 (no wait); timeout for QueryOutput call in ms.
// Usage Settings
#define AMF_VIDEO_ENCODER_AV1_USAGE L"Av1Usage" // amf_int64(AMF_VIDEO_ENCODER_AV1_USAGE_ENUM); default = N/A; Encoder usage. fully configures parameter set.
// Session Configuration
#define AMF_VIDEO_ENCODER_AV1_FRAMESIZE L"Av1FrameSize" // AMFSize; default = 0,0; Frame size
#define AMF_VIDEO_ENCODER_AV1_COLOR_BIT_DEPTH L"Av1ColorBitDepth" // amf_int64(AMF_COLOR_BIT_DEPTH_ENUM); default = AMF_COLOR_BIT_DEPTH_8
#define AMF_VIDEO_ENCODER_AV1_PROFILE L"Av1Profile" // amf_int64(AMF_VIDEO_ENCODER_AV1_PROFILE_ENUM) ; default = depends on USAGE; the codec profile of the coded bitstream
#define AMF_VIDEO_ENCODER_AV1_LEVEL L"Av1Level" // amf_int64 (AMF_VIDEO_ENCODER_AV1_LEVEL_ENUM); default = depends on USAGE; the codec level of the coded bitstream
#define AMF_VIDEO_ENCODER_AV1_TILES_PER_FRAME L"Av1NumTilesPerFrame" // amf_int64; default = 1; Number of tiles Per Frame. This is treated as suggestion. The actual number of tiles might be different due to compliance or encoder limitation.
#define AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET L"Av1QualityPreset" // amf_int64(AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_ENUM); default = depends on USAGE; Quality Preset
// Codec Configuration
#define AMF_VIDEO_ENCODER_AV1_SCREEN_CONTENT_TOOLS L"Av1ScreenContentTools" // bool; default = depends on USAGE; If true, allow enabling screen content tools by AMF_VIDEO_ENCODER_AV1_PALETTE_MODE_ENABLE and AMF_VIDEO_ENCODER_AV1_FORCE_INTEGER_MV; if false, all screen content tools are disabled.
#define AMF_VIDEO_ENCODER_AV1_ORDER_HINT L"Av1OrderHint" // bool; default = depends on USAGE; If true, code order hint; if false, don't code order hint
#define AMF_VIDEO_ENCODER_AV1_FRAME_ID L"Av1FrameId" // bool; default = depends on USAGE; If true, code frame id; if false, don't code frame id
#define AMF_VIDEO_ENCODER_AV1_TILE_GROUP_OBU L"Av1TileGroupObu" // bool; default = depends on USAGE; If true, code FrameHeaderObu + TileGroupObu and each TileGroupObu contains one tile; if false, code FrameObu.
#define AMF_VIDEO_ENCODER_AV1_CDEF_MODE L"Av1CdefMode" // amd_int64(AMF_VIDEO_ENCODER_AV1_CDEF_MODE_ENUM); default = depends on USAGE; Cdef mode
#define AMF_VIDEO_ENCODER_AV1_ERROR_RESILIENT_MODE L"Av1ErrorResilientMode" // bool; default = depends on USAGE; If true, enable error resilient mode; if false, disable error resilient mode
// Rate Control and Quality Enhancement
#define AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD L"Av1RateControlMethod" // amf_int64(AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_ENUM); default = depends on USAGE; Rate Control Method
#define AMF_VIDEO_ENCODER_AV1_QVBR_QUALITY_LEVEL L"Av1QvbrQualityLevel" // amf_int64; default = 23; QVBR quality level; range = 1-51
#define AMF_VIDEO_ENCODER_AV1_INITIAL_VBV_BUFFER_FULLNESS L"Av1InitialVBVBufferFullness" // amf_int64; default = depends on USAGE; Initial VBV Buffer Fullness 0=0% 64=100%
// Alignment Mode Configuration
#define AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE L"Av1AlignmentMode" // amf_int64(AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_ENUM); default = AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_ONLY; Alignment Mode.
#define AMF_VIDEO_ENCODER_AV1_PRE_ANALYSIS_ENABLE L"Av1EnablePreAnalysis" // bool; default = depends on USAGE; If true, enables the pre-analysis module. Refer to AMF Video PreAnalysis API reference for more details. If false, disable the pre-analysis module.
#define AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_PREENCODE L"Av1RateControlPreEncode" // bool; default = depends on USAGE; If true, enables pre-encode assist in rate control; if false, disables pre-encode assist in rate control.
#define AMF_VIDEO_ENCODER_AV1_HIGH_MOTION_QUALITY_BOOST L"Av1HighMotionQualityBoost" // bool; default = depends on USAGE; If true, enable high motion quality boost mode; if false, disable high motion quality boost mode.
#define AMF_VIDEO_ENCODER_AV1_AQ_MODE L"Av1AQMode" // amd_int64(AMF_VIDEO_ENCODER_AV1_AQ_MODE_ENUM); default = depends on USAGE; AQ mode
// Picture Management Configuration
#define AMF_VIDEO_ENCODER_AV1_MAX_NUM_TEMPORAL_LAYERS L"Av1MaxNumOfTemporalLayers" // amf_int64; default = depends on USAGE; Max number of temporal layers might be enabled. The maximum value can be queried from AMF_VIDEO_ENCODER_AV1_CAP_MAX_NUM_TEMPORAL_LAYERS
#define AMF_VIDEO_ENCODER_AV1_MAX_LTR_FRAMES L"Av1MaxNumLTRFrames" // amf_int64; default = depends on USAGE; Max number of LTR frames. The maximum value can be queried from AMF_VIDEO_ENCODER_AV1_CAP_MAX_NUM_LTR_FRAMES
#define AMF_VIDEO_ENCODER_AV1_MAX_NUM_REFRAMES L"Av1MaxNumRefFrames" // amf_int64; default = 1; Maximum number of reference frames
// color conversion
#define AMF_VIDEO_ENCODER_AV1_INPUT_HDR_METADATA L"Av1InHDRMetadata" // AMFBuffer containing AMFHDRMetadata; default NULL
// Miscellaneous
#define AMF_VIDEO_ENCODER_AV1_EXTRA_DATA L"Av1ExtraData" // AMFInterface* - > AMFBuffer*; buffer to retrieve coded sequence header
// *** Dynamic properties - can be set anytime ***
// Codec Configuration
#define AMF_VIDEO_ENCODER_AV1_PALETTE_MODE L"Av1PaletteMode" // bool; default = depends on USAGE; If true, enable palette mode; if false, disable palette mode. Valid only when AMF_VIDEO_ENCODER_AV1_SCREEN_CONTENT_TOOLS is true.
#define AMF_VIDEO_ENCODER_AV1_FORCE_INTEGER_MV L"Av1ForceIntegerMv" // bool; default = depends on USAGE; If true, enable force integer MV; if false, disable force integer MV. Valid only when AMF_VIDEO_ENCODER_AV1_SCREEN_CONTENT_TOOLS is true.
#define AMF_VIDEO_ENCODER_AV1_CDF_UPDATE L"Av1CdfUpdate" // bool; default = depends on USAGE; If true, enable CDF update; if false, disable CDF update.
#define AMF_VIDEO_ENCODER_AV1_CDF_FRAME_END_UPDATE_MODE L"Av1CdfFrameEndUpdateMode" // amd_int64(AMF_VIDEO_ENCODER_AV1_CDF_FRAME_END_UPDATE_MODE_ENUM); default = depends on USAGE; CDF frame end update mode
// Rate Control and Quality Enhancement
#define AMF_VIDEO_ENCODER_AV1_VBV_BUFFER_SIZE L"Av1VBVBufferSize" // amf_int64; default = depends on USAGE; VBV Buffer Size in bits
#define AMF_VIDEO_ENCODER_AV1_FRAMERATE L"Av1FrameRate" // AMFRate; default = depends on usage; Frame Rate
#define AMF_VIDEO_ENCODER_AV1_ENFORCE_HRD L"Av1EnforceHRD" // bool; default = depends on USAGE; If true, enforce HRD; if false, HRD is not enforced.
#define AMF_VIDEO_ENCODER_AV1_FILLER_DATA L"Av1FillerData" // bool; default = depends on USAGE; If true, code filler data when needed; if false, don't code filler data.
#define AMF_VIDEO_ENCODER_AV1_TARGET_BITRATE L"Av1TargetBitrate" // amf_int64; default = depends on USAGE; Target bit rate in bits
#define AMF_VIDEO_ENCODER_AV1_PEAK_BITRATE L"Av1PeakBitrate" // amf_int64; default = depends on USAGE; Peak bit rate in bits
#define AMF_VIDEO_ENCODER_AV1_MAX_COMPRESSED_FRAME_SIZE L"Av1MaxCompressedFrameSize" // amf_int64; default = 0; Max compressed frame Size in bits. 0 - no limit
#define AMF_VIDEO_ENCODER_AV1_MIN_Q_INDEX_INTRA L"Av1MinQIndex_Intra" // amf_int64; default = depends on USAGE; Min QIndex for intra frames; range = 0-255
#define AMF_VIDEO_ENCODER_AV1_MAX_Q_INDEX_INTRA L"Av1MaxQIndex_Intra" // amf_int64; default = depends on USAGE; Max QIndex for intra frames; range = 0-255
#define AMF_VIDEO_ENCODER_AV1_MIN_Q_INDEX_INTER L"Av1MinQIndex_Inter" // amf_int64; default = depends on USAGE; Min QIndex for inter frames; range = 0-255
#define AMF_VIDEO_ENCODER_AV1_MAX_Q_INDEX_INTER L"Av1MaxQIndex_Inter" // amf_int64; default = depends on USAGE; Max QIndex for inter frames; range = 0-255
#define AMF_VIDEO_ENCODER_AV1_Q_INDEX_INTRA L"Av1QIndex_Intra" // amf_int64; default = depends on USAGE; intra-frame QIndex; range = 0-255
#define AMF_VIDEO_ENCODER_AV1_Q_INDEX_INTER L"Av1QIndex_Inter" // amf_int64; default = depends on USAGE; inter-frame QIndex; range = 0-255
#define AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_SKIP_FRAME L"Av1RateControlSkipFrameEnable" // bool; default = depends on USAGE; If true, rate control may code skip frame when needed; if false, rate control will not code skip frame.
// Picture Management Configuration
#define AMF_VIDEO_ENCODER_AV1_GOP_SIZE L"Av1GOPSize" // amf_int64; default = depends on USAGE; GOP Size (distance between automatically inserted key frames). If 0, key frame will be inserted at first frame only. Note that GOP may be interrupted by AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE.
#define AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE L"Av1HeaderInsertionMode" // amf_int64(AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_ENUM); default = depends on USAGE; sequence header insertion mode
#define AMF_VIDEO_ENCODER_AV1_SWITCH_FRAME_INSERTION_MODE L"Av1SwitchFrameInsertionMode" // amf_int64(AMF_VIDEO_ENCODER_AV1_SWITCH_FRAME_INSERTION_MODE_ENUM); default = depends on USAGE; switch frame insertin mode
#define AMF_VIDEO_ENCODER_AV1_SWITCH_FRAME_INTERVAL L"Av1SwitchFrameInterval" // amf_int64; default = depends on USAGE; the interval between two inserted switch frames. Valid only when AMF_VIDEO_ENCODER_AV1_SWITCH_FRAME_INSERTION_MODE is AMF_VIDEO_ENCODER_AV1_SWITCH_FRAME_INSERTION_MODE_FIXED_INTERVAL.
#define AMF_VIDEO_ENCODER_AV1_NUM_TEMPORAL_LAYERS L"Av1NumTemporalLayers" // amf_int64; default = depends on USAGE; Number of temporal layers. Can be changed at any time but the change is only applied when encoding next base layer frame.
#define AMF_VIDEO_ENCODER_AV1_INTRA_REFRESH_MODE L"Av1IntraRefreshMode" // amf_int64(AMF_VIDEO_ENCODER_AV1_INTRA_REFRESH_MODE_ENUM); default AMF_VIDEO_ENCODER_AV1_INTRA_REFRESH_MODE__DISABLED
#define AMF_VIDEO_ENCODER_AV1_INTRAREFRESH_STRIPES L"Av1IntraRefreshNumOfStripes" // amf_int64; default = N/A; Valid only when intra refresh is enabled.
// color conversion
#define AMF_VIDEO_ENCODER_AV1_INPUT_COLOR_PROFILE L"Av1InputColorProfile" // amf_int64(AMF_VIDEO_CONVERTER_COLOR_PROFILE_ENUM); default = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN - mean AUTO by size
#define AMF_VIDEO_ENCODER_AV1_INPUT_TRANSFER_CHARACTERISTIC L"Av1InputColorTransferChar" // amf_int64(AMF_COLOR_TRANSFER_CHARACTERISTIC_ENUM); default = AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED, ISO/IEC 23001-8_2013 section 7.2 See VideoDecoderUVD.h for enum
#define AMF_VIDEO_ENCODER_AV1_INPUT_COLOR_PRIMARIES L"Av1InputColorPrimaries" // amf_int64(AMF_COLOR_PRIMARIES_ENUM); default = AMF_COLOR_PRIMARIES_UNDEFINED, ISO/IEC 23001-8_2013 section 7.1 See ColorSpace.h for enum
#define AMF_VIDEO_ENCODER_AV1_OUTPUT_COLOR_PROFILE L"Av1OutputColorProfile" // amf_int64(AMF_VIDEO_CONVERTER_COLOR_PROFILE_ENUM); default = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN - mean AUTO by size
#define AMF_VIDEO_ENCODER_AV1_OUTPUT_TRANSFER_CHARACTERISTIC L"Av1OutputColorTransferChar" // amf_int64(AMF_COLOR_TRANSFER_CHARACTERISTIC_ENUM); default = AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED, ISO/IEC 23001-8_2013 ?7.2 See VideoDecoderUVD.h for enum
#define AMF_VIDEO_ENCODER_AV1_OUTPUT_COLOR_PRIMARIES L"Av1OutputColorPrimaries" // amf_int64(AMF_COLOR_PRIMARIES_ENUM); default = AMF_COLOR_PRIMARIES_UNDEFINED, ISO/IEC 23001-8_2013 section 7.1 See ColorSpace.h for enum
// Frame encode parameters
#define AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE L"Av1ForceFrameType" // amf_int64(AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_ENUM); default = AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_NONE; generate particular frame type
#define AMF_VIDEO_ENCODER_AV1_FORCE_INSERT_SEQUENCE_HEADER L"Av1ForceInsertSequenceHeader" // bool; default = false; If true, force insert sequence header with current frame;
#define AMF_VIDEO_ENCODER_AV1_MARK_CURRENT_WITH_LTR_INDEX L"Av1MarkCurrentWithLTRIndex" // amf_int64; default = N/A; Mark current frame with LTR index
#define AMF_VIDEO_ENCODER_AV1_FORCE_LTR_REFERENCE_BITFIELD L"Av1ForceLTRReferenceBitfield" // amf_int64; default = 0; force LTR bit-field
#define AMF_VIDEO_ENCODER_AV1_ROI_DATA L"Av1ROIData" // 2D AMFSurface, surface format: AMF_SURFACE_GRAY32
// Encode output parameters
#define AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE L"Av1OutputFrameType" // amf_int64(AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_ENUM); default = N/A
#define AMF_VIDEO_ENCODER_AV1_OUTPUT_MARKED_LTR_INDEX L"Av1MarkedLTRIndex" // amf_int64; default = N/A; Marked LTR index
#define AMF_VIDEO_ENCODER_AV1_OUTPUT_REFERENCED_LTR_INDEX_BITFIELD L"Av1ReferencedLTRIndexBitfield" // amf_int64; default = N/A; referenced LTR bit-field
// AV1 Encoder capabilities - exposed in AMFCaps interface
#define AMF_VIDEO_ENCODER_AV1_CAP_NUM_OF_HW_INSTANCES L"Av1CapNumOfHwInstances" // amf_int64; default = N/A; number of HW encoder instances
#define AMF_VIDEO_ENCODER_AV1_CAP_MAX_THROUGHPUT L"Av1CapMaxThroughput" // amf_int64; default = N/A; MAX throughput for AV1 encoder in MB (16 x 16 pixel)
#define AMF_VIDEO_ENCODER_AV1_CAP_REQUESTED_THROUGHPUT L"Av1CapRequestedThroughput" // amf_int64; default = N/A; Currently total requested throughput for AV1 encode in MB (16 x 16 pixel)
#define AMF_VIDEO_ENCODER_AV1_CAP_COLOR_CONVERSION L"Av1CapColorConversion" // amf_int64(AMF_ACCELERATION_TYPE); default = N/A; type of supported color conversion. default AMF_ACCEL_GPU
#define AMF_VIDEO_ENCODER_AV1_CAP_PRE_ANALYSIS L"Av1PreAnalysis" // amf_bool - pre analysis module is available for AV1 UVE encoder, n/a for the other encoders
#define AMF_VIDEO_ENCODER_AV1_CAP_MAX_BITRATE L"Av1MaxBitrate" // amf_int64; default = N/A; Maximum bit rate in bits
#define AMF_VIDEO_ENCODER_AV1_CAP_MAX_PROFILE L"Av1MaxProfile" // amf_int64(AMF_VIDEO_ENCODER_AV1_PROFILE_ENUM); default = N/A; max value of code profile
#define AMF_VIDEO_ENCODER_AV1_CAP_MAX_LEVEL L"Av1MaxLevel" // amf_int64(AMF_VIDEO_ENCODER_AV1_LEVEL_ENUM); default = N/A; max value of codec level
#define AMF_VIDEO_ENCODER_AV1_CAP_MAX_NUM_TEMPORAL_LAYERS L"Av1CapMaxNumTemporalLayers" // amf_int64; default = N/A; The cap of maximum number of temporal layers
#define AMF_VIDEO_ENCODER_AV1_CAP_MAX_NUM_LTR_FRAMES L"Av1CapMaxNumLTRFrames" // amf_int64; default = N/A; The cap of maximum number of LTR frames. This value is calculated based on current value of AMF_VIDEO_ENCODER_AV1_MAX_NUM_TEMPORAL_LAYERS.
#endif //#ifndef AMF_VideoEncoderAV1_h

View File

@@ -80,7 +80,10 @@ enum AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_ENUM
AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP = 0,
AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR,
AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR,
AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR
AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR,
AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_QUALITY_VBR,
AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_HIGH_QUALITY_VBR,
AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_HIGH_QUALITY_CBR
};
enum AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_ENUM
@@ -145,9 +148,10 @@ enum AMF_VIDEO_ENCODER_HEVC_LTR_MODE_ENUM
#define AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET L"HevcQualityPreset" // amf_int64(AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_ENUM); default = depends on USAGE; Quality Preset
#define AMF_VIDEO_ENCODER_HEVC_EXTRADATA L"HevcExtraData" // AMFInterface* - > AMFBuffer*; SPS/PPS buffer - read-only
#define AMF_VIDEO_ENCODER_HEVC_ASPECT_RATIO L"HevcAspectRatio" // AMFRatio; default = 1, 1
#define AMF_VIDEO_ENCODER_HEVC_LOWLATENCY_MODE L"LowLatencyInternal" // bool; default = false, enables low latency mode
#define AMF_VIDEO_ENCODER_HEVC_LOWLATENCY_MODE L"LowLatencyInternal" // bool; default = false, enables low latency mode
#define AMF_VIDEO_ENCODER_HEVC_PRE_ANALYSIS_ENABLE L"HevcEnablePreAnalysis" // bool; default = false; enables the pre-analysis module. Currently only works in AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR mode. Refer to AMF Video PreAnalysis API reference for more details.
#define AMF_VIDEO_ENCODER_HEVC_NOMINAL_RANGE L"HevcNominalRange" // amf_int64(AMF_VIDEO_ENCODER_HEVC_NOMINAL_RANGE); default = amf_int64(AMF_VIDEO_ENCODER_HEVC_NOMINAL_RANGE_STUDIO); property is bool but amf_int64 also works for backward compatibility.
#define AMF_VIDEO_ENCODER_HEVC_NOMINAL_RANGE L"HevcNominalRange" // amf_int64(AMF_VIDEO_ENCODER_HEVC_NOMINAL_RANGE); default = amf_int64(AMF_VIDEO_ENCODER_HEVC_NOMINAL_RANGE_STUDIO); property is bool but amf_int64 also works for backward compatibility.
#define AMF_VIDEO_ENCODER_HEVC_MAX_NUM_TEMPORAL_LAYERS L"HevcMaxNumOfTemporalLayers" // amf_int64; default = 1; Max number of temporal layers.
// Picture control properties
#define AMF_VIDEO_ENCODER_HEVC_NUM_GOPS_PER_IDR L"HevcGOPSPerIDR" // amf_int64; default = 1; The frequency to insert IDR as start of a GOP. 0 means no IDR will be inserted.
@@ -159,6 +163,7 @@ enum AMF_VIDEO_ENCODER_HEVC_LTR_MODE_ENUM
// Rate control properties
#define AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD L"HevcRateControlMethod" // amf_int64(AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_ENUM); default = depends on USAGE; Rate Control Method
#define AMF_VIDEO_ENCODER_HEVC_QVBR_QUALITY_LEVEL L"HevcQvbrQualityLevel" // amf_int64; default = 23; QVBR quality level; range = 1-51
#define AMF_VIDEO_ENCODER_HEVC_VBV_BUFFER_SIZE L"HevcVBVBufferSize" // amf_int64; default = depends on USAGE; VBV Buffer Size in bits
#define AMF_VIDEO_ENCODER_HEVC_INITIAL_VBV_BUFFER_FULLNESS L"HevcInitialVBVBufferFullness" // amf_int64; default = 64; Initial VBV Buffer Fullness 0=0% 64=100%
#define AMF_VIDEO_ENCODER_HEVC_ENABLE_VBAQ L"HevcEnableVBAQ" // // bool; default = depends on USAGE; Enable auto VBAQ
@@ -213,6 +218,9 @@ enum AMF_VIDEO_ENCODER_HEVC_LTR_MODE_ENUM
#define AMF_VIDEO_ENCODER_HEVC_INPUT_HDR_METADATA L"HevcInHDRMetadata" // AMFBuffer containing AMFHDRMetadata; default NULL
//#define AMF_VIDEO_ENCODER_HEVC_OUTPUT_HDR_METADATA L"HevcOutHDRMetadata" // AMFBuffer containing AMFHDRMetadata; default NULL
// SVC
#define AMF_VIDEO_ENCODER_HEVC_NUM_TEMPORAL_LAYERS L"HevcNumOfTemporalLayers" // amf_int64; default = 1; Number of temporal layers. Can be changed at any time but the change is only applied when encoding next base layer frame.
// DPB management
#define AMF_VIDEO_ENCODER_HEVC_PICTURE_TRANSFER_MODE L"HevcPicTransferMode" // amf_int64(AMF_VIDEO_ENCODER_HEVC_PICTURE_TRANSFER_MODE_ENUM); default = AMF_VIDEO_ENCODER_HEVC_PICTURE_TRANSFER_MODE_OFF - whether to exchange reference/reconstructed pic between encoder and application
@@ -282,6 +290,7 @@ enum AMF_VIDEO_ENCODER_HEVC_LTR_MODE_ENUM
#define AMF_VIDEO_ENCODER_HEVC_CAP_MAX_LEVEL L"HevcMaxLevel" // amf_int64 maximum profile level
#define AMF_VIDEO_ENCODER_HEVC_CAP_MIN_REFERENCE_FRAMES L"HevcMinReferenceFrames" // amf_int64 minimum number of reference frames
#define AMF_VIDEO_ENCODER_HEVC_CAP_MAX_REFERENCE_FRAMES L"HevcMaxReferenceFrames" // amf_int64 maximum number of reference frames
#define AMF_VIDEO_ENCODER_HEVC_CAP_MAX_TEMPORAL_LAYERS L"HevcMaxTemporalLayers" // amf_int64 maximum number of temporal layers
#define AMF_VIDEO_ENCODER_HEVC_CAP_NUM_OF_HW_INSTANCES L"HevcNumOfHwInstances" // amf_int64 number of HW encoder instances
#define AMF_VIDEO_ENCODER_HEVC_CAP_COLOR_CONVERSION L"HevcColorConversion" // amf_int64(AMF_ACCELERATION_TYPE) - type of supported color conversion. default AMF_ACCEL_GPU
#define AMF_VIDEO_ENCODER_HEVC_CAP_PRE_ANALYSIS L"HevcPreAnalysis" // amf_bool - pre analysis module is available for HEVC UVE encoder, n/a for the other encoders

View File

@@ -79,7 +79,9 @@ enum AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_ENUM
AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR,
AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR,
AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR,
AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_QUALITY_VBR
AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_QUALITY_VBR,
AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_HIGH_QUALITY_VBR,
AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_HIGH_QUALITY_CBR
};
enum AMF_VIDEO_ENCODER_QUALITY_PRESET_ENUM
@@ -164,6 +166,7 @@ enum AMF_VIDEO_ENCODER_LTR_MODE_ENUM
#define AMF_VIDEO_ENCODER_RATE_CONTROL_PREANALYSIS_ENABLE L"RateControlPreanalysisEnable" // amf_int64(AMF_VIDEO_ENCODER_PREENCODE_MODE_ENUM); default = AMF_VIDEO_ENCODER_PREENCODE_DISABLED; enables pre-encode assisted rate control. Deprecated, please use AMF_VIDEO_ENCODER_PREENCODE_ENABLE instead.
#define AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD L"RateControlMethod" // amf_int64(AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_ENUM); default = depends on USAGE; Rate Control Method
#define AMF_VIDEO_ENCODER_QVBR_QUALITY_LEVEL L"QvbrQualityLevel" // amf_int64; default = 23; QVBR quality level; range = 1-51
#define AMF_VIDEO_ENCODER_MAX_NUM_TEMPORAL_LAYERS L"MaxNumOfTemporalLayers" // amf_int64; default = 1; Max number of temporal layers.
#if !defined(__GNUC__) && !defined(__clang__)
#pragma deprecated("AMF_VIDEO_ENCODER_RATE_CONTROL_PREANALYSIS_ENABLE")
#endif

View File

@@ -2,6 +2,7 @@
#include "../external/AMF/include/core/Trace.h"
#include "../external/AMF/include/components/VideoEncoderVCE.h"
#include "../external/AMF/include/components/VideoEncoderHEVC.h"
#include "../external/AMF/include/components/VideoEncoderAV1.h"
#include <util/windows/ComPtr.hpp>
@@ -24,6 +25,7 @@ struct adapter_caps {
bool is_amd = false;
bool supports_avc = false;
bool supports_hevc = false;
bool supports_av1 = false;
};
static AMFFactory *amf_factory = nullptr;
@@ -81,6 +83,7 @@ static bool get_adapter_caps(IDXGIFactory *factory, uint32_t adapter_idx)
caps.supports_avc = has_encoder(amf_context, AMFVideoEncoderVCE_AVC);
caps.supports_hevc = has_encoder(amf_context, AMFVideoEncoder_HEVC);
caps.supports_av1 = has_encoder(amf_context, AMFVideoEncoder_AV1);
return true;
}
@@ -145,6 +148,8 @@ try {
caps.supports_avc ? "true" : "false");
printf("supports_hevc=%s\n",
caps.supports_hevc ? "true" : "false");
printf("supports_av1=%s\n",
caps.supports_av1 ? "true" : "false");
}
return 0;

View File

@@ -17,25 +17,40 @@ static void amf_apply_opt(amf_base *enc, obs_option *opt)
{
bool avc = enc->codec == amf_codec_type::AVC;
bool hevc = enc->codec == amf_codec_type::HEVC;
bool av1 = enc->codec == amf_codec_type::AV1;
if (strcmp(opt->name, "g") == 0 || strcmp(opt->name, "keyint") == 0) {
int val = atoi(opt->value);
if (enc->codec == amf_codec_type::AVC)
if (avc)
set_avc_opt(IDR_PERIOD, val);
else
else if (hevc)
set_hevc_opt(NUM_GOPS_PER_IDR, val);
else if (av1)
set_av1_opt(GOP_SIZE, val);
} else if (strcmp(opt->name, "usage") == 0) {
if (strcmp(opt->value, "transcoding") == 0) {
set_enum_opt(USAGE, TRANSCONDING);
set_enum_opt(USAGE, TRANSCODING);
} else if (strcmp(opt->value, "ultralowlatency") == 0) {
set_enum_opt(USAGE, ULTRA_LOW_LATENCY);
if (avc)
set_avc_enum(USAGE, ULTRA_LOW_LATENCY);
else if (hevc)
set_hevc_enum(USAGE, ULTRA_LOW_LATENCY);
else
warn("Invalid value for %s: %s", opt->name,
opt->value);
} else if (strcmp(opt->value, "lowlatency") == 0) {
set_enum_opt(USAGE, LOW_LATENCY);
} else if (strcmp(opt->value, "webcam") == 0) {
set_enum_opt(USAGE, WEBCAM);
if (avc)
set_avc_enum(USAGE, WEBCAM);
else if (hevc)
set_hevc_enum(USAGE, WEBCAM);
else
warn("Invalid value for %s: %s", opt->name,
opt->value);
} else {
warn("Invalid value for %s: %s", opt->name, opt->value);
}
@@ -69,7 +84,12 @@ static void amf_apply_opt(amf_base *enc, obs_option *opt)
val.erase(pos, 1);
int level = std::stoi(val);
set_opt(PROFILE_LEVEL, level);
if (avc)
set_avc_opt(PROFILE_LEVEL, level);
else if (hevc)
set_hevc_opt(PROFILE_LEVEL, level);
else
warn("Invalid value for %s: %s", opt->name, opt->value);
} else if (strcmp(opt->name, "quality") == 0) {
@@ -106,42 +126,82 @@ static void amf_apply_opt(amf_base *enc, obs_option *opt)
} else if (strcmp(opt->name, "filler_data") == 0) {
bool val = str_to_bool(opt->value);
set_opt(FILLER_DATA_ENABLE, val);
if (avc)
set_avc_opt(FILLER_DATA_ENABLE, val);
else if (hevc)
set_hevc_opt(FILLER_DATA_ENABLE, val);
else
warn("Invalid value for %s: %s", opt->name, opt->value);
} else if (strcmp(opt->name, "vbaq") == 0) {
bool val = str_to_bool(opt->value);
set_opt(ENABLE_VBAQ, val);
if (avc)
set_avc_opt(ENABLE_VBAQ, val);
else if (hevc)
set_hevc_opt(ENABLE_VBAQ, val);
else
warn("Invalid value for %s: %s", opt->name, opt->value);
} else if (strcmp(opt->name, "qp_i") == 0) {
int val = atoi(opt->value);
set_opt(QP_I, val);
if (avc)
set_avc_opt(QP_I, val);
else if (hevc)
set_hevc_opt(QP_I, val);
else
warn("Invalid value for %s: %s", opt->name, opt->value);
} else if (strcmp(opt->name, "qp_p") == 0) {
int val = atoi(opt->value);
set_opt(QP_P, val);
if (avc)
set_avc_opt(QP_P, val);
else if (hevc)
set_hevc_opt(QP_P, val);
else
warn("Invalid value for %s: %s", opt->name, opt->value);
} else if (strcmp(opt->name, "me_half_pel") == 0) {
bool val = str_to_bool(opt->value);
set_opt(MOTION_HALF_PIXEL, val);
if (avc)
set_avc_opt(MOTION_HALF_PIXEL, val);
else if (hevc)
set_hevc_opt(MOTION_HALF_PIXEL, val);
else
warn("Invalid value for %s: %s", opt->name, opt->value);
} else if (strcmp(opt->name, "me_quarter_pel") == 0) {
bool val = str_to_bool(opt->value);
set_opt(MOTION_QUARTERPIXEL, val);
if (avc)
set_avc_opt(MOTION_QUARTERPIXEL, val);
else if (hevc)
set_hevc_opt(MOTION_QUARTERPIXEL, val);
else
warn("Invalid value for %s: %s", opt->name, opt->value);
} else if (strcmp(opt->name, "aud") == 0) {
bool val = str_to_bool(opt->value);
set_opt(INSERT_AUD, val);
if (avc)
set_avc_opt(INSERT_AUD, val);
else if (hevc)
set_hevc_opt(INSERT_AUD, val);
else
warn("Invalid value for %s: %s", opt->name, opt->value);
} else if (strcmp(opt->name, "max_au_size") == 0) {
int val = atoi(opt->value);
set_opt(MAX_AU_SIZE, val);
if (avc)
set_avc_opt(MAX_AU_SIZE, val);
else if (hevc)
set_hevc_opt(MAX_AU_SIZE, val);
else
warn("Invalid value for %s: %s", opt->name, opt->value);
} else if (avc && strcmp(opt->name, "preanalysis") == 0) {

View File

@@ -16,6 +16,7 @@
#include "external/AMF/include/components/VideoEncoderHEVC.h"
#include "external/AMF/include/components/VideoEncoderVCE.h"
#include "external/AMF/include/components/VideoEncoderAV1.h"
#include "external/AMF/include/core/Factory.h"
#include "external/AMF/include/core/Trace.h"
@@ -63,6 +64,7 @@ struct adapter_caps {
bool is_amd = false;
bool supports_avc = false;
bool supports_hevc = false;
bool supports_av1 = false;
};
/* ------------------------------------------------------------------------- */
@@ -80,6 +82,7 @@ static uint64_t amf_version = 0;
enum class amf_codec_type {
AVC,
HEVC,
AV1,
};
struct amf_base {
@@ -213,25 +216,34 @@ static void set_amf_property(amf_base *enc, const wchar_t *name, const T &value)
set_amf_property(enc, AMF_VIDEO_ENCODER_##name, value)
#define set_hevc_property(enc, name, value) \
set_amf_property(enc, AMF_VIDEO_ENCODER_HEVC_##name, value)
#define set_av1_property(enc, name, value) \
set_amf_property(enc, AMF_VIDEO_ENCODER_AV1_##name, value)
#define get_avc_property(enc, name, value) \
get_amf_property(enc, AMF_VIDEO_ENCODER_##name, value)
#define get_hevc_property(enc, name, value) \
get_amf_property(enc, AMF_VIDEO_ENCODER_HEVC_##name, value)
#define get_av1_property(enc, name, value) \
get_amf_property(enc, AMF_VIDEO_ENCODER_AV1_##name, value)
#define get_opt_name(name) \
((enc->codec == amf_codec_type::AVC) ? AMF_VIDEO_ENCODER_##name \
: AMF_VIDEO_ENCODER_HEVC_##name)
: (enc->codec == amf_codec_type::HEVC) \
? AMF_VIDEO_ENCODER_HEVC_##name \
: AMF_VIDEO_ENCODER_AV1_##name)
#define set_opt(name, value) set_amf_property(enc, get_opt_name(name), value)
#define get_opt(name, value) get_amf_property(enc, get_opt_name(name), value)
#define set_avc_opt(name, value) set_avc_property(enc, name, value)
#define set_hevc_opt(name, value) set_hevc_property(enc, name, value)
#define set_av1_opt(name, value) set_av1_property(enc, name, value)
#define set_enum_opt(name, value) \
set_amf_property(enc, get_opt_name(name), get_opt_name(name##_##value))
#define set_avc_enum(name, value) \
set_avc_property(enc, name, AMF_VIDEO_ENCODER_##name##_##value)
#define set_hevc_enum(name, value) \
set_hevc_property(enc, name, AMF_VIDEO_ENCODER_HEVC_##name##_##value)
#define set_av1_enum(name, value) \
set_av1_property(enc, name, AMF_VIDEO_ENCODER_AV1_##name##_##value)
/* ------------------------------------------------------------------------- */
/* Implementation */
@@ -397,32 +409,74 @@ static inline void calc_throughput(amf_base *enc)
mb_frame * (amf_int64)enc->fps_num / (amf_int64)enc->fps_den;
}
static inline int get_avc_preset(amf_base *enc, const char *preset);
static inline int get_hevc_preset(amf_base *enc, const char *preset);
static inline int get_av1_preset(amf_base *enc, const char *preset);
static inline int get_preset(amf_base *enc, const char *preset)
{
if (enc->codec == amf_codec_type::AVC)
return get_avc_preset(enc, preset);
else if (enc->codec == amf_codec_type::HEVC)
return get_hevc_preset(enc, preset);
else if (enc->codec == amf_codec_type::AV1)
return get_av1_preset(enc, preset);
return 0;
}
static inline void refresh_throughput_caps(amf_base *enc, const char *&preset)
{
AMF_RESULT res = AMF_OK;
AMFCapsPtr caps;
set_opt(QUALITY_PRESET, get_preset(enc, preset));
res = enc->amf_encoder->GetCaps(&caps);
if (res == AMF_OK) {
caps->GetProperty(get_opt_name(CAP_MAX_THROUGHPUT),
&enc->max_throughput);
}
}
static inline void check_preset_compatibility(amf_base *enc,
const char *&preset)
{
/* 1.8 * current base throughput == quality,
* 1.1 * current base throughput == balanced */
static constexpr amf_int64 throughput_quality_mul = 18;
static constexpr amf_int64 throughput_balanced_mul = 11;
/* The throughput depends on the current preset and the other static
* encoder properties. If the throughput is lower than the max
* throughput, switch to a lower preset. */
if (astrcmpi(preset, "highQuality") == 0) {
if (!enc->max_throughput) {
preset = "quality";
set_opt(QUALITY_PRESET, get_preset(enc, preset));
} else {
if (enc->max_throughput < enc->throughput) {
preset = "quality";
refresh_throughput_caps(enc, preset);
}
}
}
/* if the throughput * 1.8 is lower than the max throughput, switch to
* a lower preset */
if (astrcmpi(preset, "quality") == 0) {
if (!enc->max_throughput) {
preset = "balanced";
set_opt(QUALITY_PRESET, get_preset(enc, preset));
} else {
amf_int64 req_throughput =
enc->throughput * throughput_quality_mul / 10;
if (enc->max_throughput < req_throughput)
if (enc->max_throughput < enc->throughput) {
preset = "balanced";
refresh_throughput_caps(enc, preset);
}
}
}
if (astrcmpi(preset, "balanced") == 0) {
amf_int64 req_throughput =
enc->throughput * throughput_balanced_mul / 10;
if (enc->max_throughput && enc->max_throughput < req_throughput)
if (enc->max_throughput &&
enc->max_throughput < enc->throughput) {
preset = "speed";
refresh_throughput_caps(enc, preset);
}
}
}
@@ -447,27 +501,60 @@ static void convert_to_encoder_packet(amf_base *enc, AMFDataPtr &data,
enc->packet_data = AMFBufferPtr(data);
data->GetProperty(L"PTS", &packet->pts);
bool hevc = enc->codec == amf_codec_type::HEVC;
const wchar_t *get_output_type =
hevc ? AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE
: AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE;
const wchar_t *get_output_type;
switch (enc->codec) {
case amf_codec_type::AVC:
get_output_type = AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE;
break;
case amf_codec_type::HEVC:
get_output_type = AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE;
break;
case amf_codec_type::AV1:
get_output_type = AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE;
break;
}
uint64_t type;
data->GetProperty(get_output_type, &type);
uint64_t type = 0;
AMF_RESULT res = data->GetProperty(get_output_type, &type);
if (res != AMF_OK)
throw amf_error("Failed to GetProperty(): encoder output "
"data type",
res);
switch (type) {
case AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR:
packet->priority = OBS_NAL_PRIORITY_HIGHEST;
break;
case AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_I:
packet->priority = OBS_NAL_PRIORITY_HIGH;
break;
case AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_P:
packet->priority = OBS_NAL_PRIORITY_LOW;
break;
case AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_B:
packet->priority = OBS_NAL_PRIORITY_DISPOSABLE;
break;
if (enc->codec == amf_codec_type::AVC ||
enc->codec == amf_codec_type::HEVC) {
switch (type) {
case AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR:
packet->priority = OBS_NAL_PRIORITY_HIGHEST;
break;
case AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_I:
packet->priority = OBS_NAL_PRIORITY_HIGH;
break;
case AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_P:
packet->priority = OBS_NAL_PRIORITY_LOW;
break;
case AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_B:
packet->priority = OBS_NAL_PRIORITY_DISPOSABLE;
break;
}
} else if (enc->codec == amf_codec_type::AV1) {
switch (type) {
case AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_KEY:
packet->priority = OBS_NAL_PRIORITY_HIGHEST;
break;
case AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_INTRA_ONLY:
packet->priority = OBS_NAL_PRIORITY_HIGH;
break;
case AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_INTER:
packet->priority = OBS_NAL_PRIORITY_LOW;
break;
case AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_SWITCH:
packet->priority = OBS_NAL_PRIORITY_DISPOSABLE;
break;
case AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_SHOW_EXISTING:
packet->priority = OBS_NAL_PRIORITY_DISPOSABLE;
break;
}
}
packet->data = (uint8_t *)enc->packet_data->GetNative();
@@ -769,6 +856,23 @@ static void h265_video_info_fallback(void *, struct video_scale_info *info)
}
}
static void av1_video_info_fallback(void *, struct video_scale_info *info)
{
switch (info->format) {
case VIDEO_FORMAT_RGBA:
case VIDEO_FORMAT_BGRA:
case VIDEO_FORMAT_BGRX:
info->format = VIDEO_FORMAT_RGBA;
break;
case VIDEO_FORMAT_I010:
case VIDEO_FORMAT_P010:
info->format = VIDEO_FORMAT_P010;
break;
default:
info->format = VIDEO_FORMAT_NV12;
}
}
static bool amf_create_encoder(amf_base *enc)
try {
AMF_RESULT res;
@@ -787,8 +891,10 @@ try {
if (enc->fallback) {
if (enc->codec == amf_codec_type::AVC)
h264_video_info_fallback(NULL, &info);
else
else if (enc->codec == amf_codec_type::HEVC)
h265_video_info_fallback(NULL, &info);
else
av1_video_info_fallback(NULL, &info);
}
enc->cx = obs_encoder_get_width(enc->encoder);
@@ -868,10 +974,21 @@ try {
enc->init();
res = amf_factory->CreateComponent(enc->amf_context,
enc->codec == amf_codec_type::HEVC
? AMFVideoEncoder_HEVC
: AMFVideoEncoderVCE_AVC,
const wchar_t *codec = nullptr;
switch (enc->codec) {
case (amf_codec_type::AVC):
codec = AMFVideoEncoderVCE_AVC;
break;
case (amf_codec_type::HEVC):
codec = AMFVideoEncoder_HEVC;
break;
case (amf_codec_type::AV1):
codec = AMFVideoEncoder_AV1;
break;
default:
codec = AMFVideoEncoder_HEVC;
}
res = amf_factory->CreateComponent(enc->amf_context, codec,
&enc->amf_encoder);
if (res != AMF_OK)
throw amf_error("CreateComponent failed", res);
@@ -891,14 +1008,19 @@ static void amf_destroy(void *data)
delete enc;
}
static void check_texture_encode_capability(obs_encoder_t *encoder, bool hevc)
static void check_texture_encode_capability(obs_encoder_t *encoder,
amf_codec_type codec)
{
obs_video_info ovi;
obs_get_video_info(&ovi);
bool avc = amf_codec_type::AVC == codec;
bool hevc = amf_codec_type::HEVC == codec;
bool av1 = amf_codec_type::AV1 == codec;
if (obs_encoder_scaling_enabled(encoder))
throw "Encoder scaling is active";
if (hevc) {
if (hevc || av1) {
if (!obs_nv12_tex_active() && !obs_p010_tex_active())
throw "NV12/P010 textures aren't active";
} else if (!obs_nv12_tex_active()) {
@@ -919,8 +1041,9 @@ static void check_texture_encode_capability(obs_encoder_t *encoder, bool hevc)
}
}
if ((hevc && !caps[ovi.adapter].supports_hevc) ||
(!hevc && !caps[ovi.adapter].supports_avc))
if ((avc && !caps[ovi.adapter].supports_avc) ||
(hevc && !caps[ovi.adapter].supports_hevc) ||
(av1 && !caps[ovi.adapter].supports_av1))
throw "Wrong adapter";
}
@@ -948,7 +1071,7 @@ static bool rate_control_modified(obs_properties_t *ppts, obs_property_t *p,
return true;
}
static obs_properties_t *amf_properties_internal(bool hevc)
static obs_properties_t *amf_properties_internal(amf_codec_type codec)
{
obs_properties_t *props = obs_properties_create();
obs_property_t *p;
@@ -960,6 +1083,12 @@ static obs_properties_t *amf_properties_internal(bool hevc)
obs_property_list_add_string(p, "CBR", "CBR");
obs_property_list_add_string(p, "CQP", "CQP");
obs_property_list_add_string(p, "VBR", "VBR");
if (amf_codec_type::AV1 == codec) {
obs_property_list_add_string(p, "VBR_LAT", "VBR_LAT");
obs_property_list_add_string(p, "QVBR", "QVBR");
obs_property_list_add_string(p, "HQVBR", "HQVBR");
obs_property_list_add_string(p, "HQCBR", "HQCBR");
}
obs_property_set_modified_callback(p, rate_control_modified);
@@ -968,7 +1097,7 @@ static obs_properties_t *amf_properties_internal(bool hevc)
obs_property_int_set_suffix(p, " Kbps");
obs_properties_add_int(props, "cqp", obs_module_text("NVENC.CQLevel"),
1, 30, 1);
0, codec == amf_codec_type::AV1 ? 63 : 51, 1);
p = obs_properties_add_int(props, "keyint_sec",
obs_module_text("KeyframeIntervalSec"), 0,
@@ -981,23 +1110,30 @@ static obs_properties_t *amf_properties_internal(bool hevc)
#define add_preset(val) \
obs_property_list_add_string(p, obs_module_text("AMF.Preset." val), val)
if (amf_codec_type::AV1 == codec) {
add_preset("highQuality");
}
add_preset("quality");
add_preset("balanced");
add_preset("speed");
#undef add_preset
if (!hevc) {
if (amf_codec_type::AVC == codec || amf_codec_type::AV1 == codec) {
p = obs_properties_add_list(props, "profile",
obs_module_text("Profile"),
OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_STRING);
#define add_profile(val) obs_property_list_add_string(p, val, val)
add_profile("high");
if (amf_codec_type::AVC == codec)
add_profile("high");
add_profile("main");
add_profile("baseline");
if (amf_codec_type::AVC == codec)
add_profile("baseline");
#undef add_profile
}
if (amf_codec_type::AVC == codec) {
obs_properties_add_int(props, "bf", obs_module_text("BFrames"),
0, 5, 1);
}
@@ -1014,13 +1150,19 @@ static obs_properties_t *amf_properties_internal(bool hevc)
static obs_properties_t *amf_avc_properties(void *unused)
{
UNUSED_PARAMETER(unused);
return amf_properties_internal(false);
return amf_properties_internal(amf_codec_type::AVC);
}
static obs_properties_t *amf_hevc_properties(void *unused)
{
UNUSED_PARAMETER(unused);
return amf_properties_internal(true);
return amf_properties_internal(amf_codec_type::HEVC);
}
static obs_properties_t *amf_av1_properties(void *unused)
{
UNUSED_PARAMETER(unused);
return amf_properties_internal(amf_codec_type::AV1);
}
/* ========================================================================= */
@@ -1028,15 +1170,11 @@ static obs_properties_t *amf_hevc_properties(void *unused)
static const char *amf_avc_get_name(void *)
{
return "AMD HW H.264";
return "AMD HW H.264 (AVC)";
}
static inline int get_avc_preset(amf_base *enc, obs_data_t *settings)
static inline int get_avc_preset(amf_base *enc, const char *preset)
{
const char *preset = obs_data_get_string(settings, "preset");
check_preset_compatibility(enc, preset);
if (astrcmpi(preset, "quality") == 0)
return AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY;
else if (astrcmpi(preset, "speed") == 0)
@@ -1130,8 +1268,6 @@ static bool amf_avc_init(void *data, obs_data_t *settings)
const char *rc_str = obs_data_get_string(settings, "rate_control");
int64_t bf = obs_data_get_int(settings, "bf");
check_preset_compatibility(enc, preset);
if (enc->bframes_supported) {
set_avc_property(enc, MAX_CONSECUTIVE_BPICTURES, 3);
set_avc_property(enc, B_PIC_PATTERN, bf);
@@ -1165,6 +1301,8 @@ static bool amf_avc_init(void *data, obs_data_t *settings)
set_avc_property(enc, DE_BLOCKING_FILTER, true);
check_preset_compatibility(enc, preset);
const char *ffmpeg_opts = obs_data_get_string(settings, "ffmpeg_opts");
if (ffmpeg_opts && *ffmpeg_opts) {
struct obs_options opts = obs_parse_options(ffmpeg_opts);
@@ -1213,9 +1351,11 @@ static void amf_avc_create_internal(amf_base *enc, obs_data_t *settings)
&enc->max_throughput);
}
const char *preset = obs_data_get_string(settings, "preset");
set_avc_property(enc, FRAMESIZE, AMFConstructSize(enc->cx, enc->cy));
set_avc_property(enc, USAGE, AMF_VIDEO_ENCODER_USAGE_TRANSCODING);
set_avc_property(enc, QUALITY_PRESET, get_avc_preset(enc, settings));
set_avc_property(enc, QUALITY_PRESET, get_avc_preset(enc, preset));
set_avc_property(enc, PROFILE, get_avc_profile(settings));
set_avc_property(enc, LOWLATENCY_MODE, false);
set_avc_property(enc, CABAC_ENABLE, AMF_VIDEO_ENCODER_UNDEFINED);
@@ -1253,7 +1393,7 @@ static void amf_avc_create_internal(amf_base *enc, obs_data_t *settings)
static void *amf_avc_create_texencode(obs_data_t *settings,
obs_encoder_t *encoder)
try {
check_texture_encode_capability(encoder, false);
check_texture_encode_capability(encoder, amf_codec_type::AVC);
std::unique_ptr<amf_texencode> enc = std::make_unique<amf_texencode>();
enc->encoder = encoder;
@@ -1357,12 +1497,8 @@ static const char *amf_hevc_get_name(void *)
return "AMD HW H.265 (HEVC)";
}
static inline int get_hevc_preset(amf_base *enc, obs_data_t *settings)
static inline int get_hevc_preset(amf_base *enc, const char *preset)
{
const char *preset = obs_data_get_string(settings, "preset");
check_preset_compatibility(enc, preset);
if (astrcmpi(preset, "balanced") == 0)
return AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_BALANCED;
else if (astrcmpi(preset, "speed") == 0)
@@ -1453,6 +1589,8 @@ static bool amf_hevc_init(void *data, obs_data_t *settings)
set_hevc_property(enc, GOP_SIZE, gop_size);
check_preset_compatibility(enc, preset);
const char *ffmpeg_opts = obs_data_get_string(settings, "ffmpeg_opts");
if (ffmpeg_opts && *ffmpeg_opts) {
struct obs_options opts = obs_parse_options(ffmpeg_opts);
@@ -1526,10 +1664,11 @@ static void amf_hevc_create_internal(amf_base *enc, obs_data_t *settings)
const bool pq = is_pq(enc);
const bool hlg = is_hlg(enc);
const bool is_hdr = pq || hlg;
const char *preset = obs_data_get_string(settings, "preset");
set_hevc_property(enc, FRAMESIZE, AMFConstructSize(enc->cx, enc->cy));
set_hevc_property(enc, USAGE, AMF_VIDEO_ENCODER_USAGE_TRANSCODING);
set_hevc_property(enc, QUALITY_PRESET, get_hevc_preset(enc, settings));
set_hevc_property(enc, QUALITY_PRESET, get_hevc_preset(enc, preset));
set_hevc_property(enc, COLOR_BIT_DEPTH,
is10bit ? AMF_COLOR_BIT_DEPTH_10
: AMF_COLOR_BIT_DEPTH_8);
@@ -1585,7 +1724,7 @@ static void amf_hevc_create_internal(amf_base *enc, obs_data_t *settings)
static void *amf_hevc_create_texencode(obs_data_t *settings,
obs_encoder_t *encoder)
try {
check_texture_encode_capability(encoder, true);
check_texture_encode_capability(encoder, amf_codec_type::HEVC);
std::unique_ptr<amf_texencode> enc = std::make_unique<amf_texencode>();
enc->encoder = encoder;
@@ -1677,6 +1816,313 @@ static void register_hevc()
#endif //ENABLE_HEVC
/* ========================================================================= */
/* AV1 Implementation */
static const char *amf_av1_get_name(void *)
{
return "AMD HW AV1";
}
static inline int get_av1_preset(amf_base *enc, const char *preset)
{
if (astrcmpi(preset, "highquality") == 0)
return AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_HIGH_QUALITY;
else if (astrcmpi(preset, "quality") == 0)
return AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_QUALITY;
else if (astrcmpi(preset, "balanced") == 0)
return AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_BALANCED;
else if (astrcmpi(preset, "speed") == 0)
return AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_SPEED;
return AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_BALANCED;
}
static inline int get_av1_rate_control(const char *rc_str)
{
if (astrcmpi(rc_str, "cqp") == 0)
return AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CONSTANT_QP;
else if (astrcmpi(rc_str, "vbr_lat") == 0)
return AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR;
else if (astrcmpi(rc_str, "vbr") == 0)
return AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR;
else if (astrcmpi(rc_str, "cbr") == 0)
return AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR;
else if (astrcmpi(rc_str, "qvbr") == 0)
return AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_QUALITY_VBR;
else if (astrcmpi(rc_str, "hqvbr") == 0)
return AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_HIGH_QUALITY_VBR;
else if (astrcmpi(rc_str, "hqcbr") == 0)
return AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_HIGH_QUALITY_CBR;
return AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR;
}
static inline int get_av1_profile(obs_data_t *settings)
{
const char *profile = obs_data_get_string(settings, "profile");
if (astrcmpi(profile, "main") == 0)
return AMF_VIDEO_ENCODER_AV1_PROFILE_MAIN;
return AMF_VIDEO_ENCODER_AV1_PROFILE_MAIN;
}
static void amf_av1_update_data(amf_base *enc, int rc, int64_t bitrate,
int64_t cq_value)
{
if (rc != AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CONSTANT_QP) {
set_av1_property(enc, TARGET_BITRATE, bitrate);
set_av1_property(enc, PEAK_BITRATE, bitrate);
set_av1_property(enc, VBV_BUFFER_SIZE, bitrate);
if (rc == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR) {
set_av1_property(enc, FILLER_DATA, true);
} else if (
rc == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR ||
rc == AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_HIGH_QUALITY_VBR) {
set_av1_property(enc, PEAK_BITRATE, bitrate * 1.5);
}
} else {
int64_t qp = cq_value * 4;
set_av1_property(enc, Q_INDEX_INTRA, qp);
set_av1_property(enc, Q_INDEX_INTER, qp);
}
}
static bool amf_av1_update(void *data, obs_data_t *settings)
try {
amf_base *enc = (amf_base *)data;
if (enc->first_update) {
enc->first_update = false;
return true;
}
int64_t bitrate = obs_data_get_int(settings, "bitrate");
int64_t cq_level = obs_data_get_int(settings, "cqp");
const char *rc_str = obs_data_get_string(settings, "rate_control");
int rc = get_av1_rate_control(rc_str);
amf_av1_update_data(enc, rc, bitrate * 1000, cq_level);
AMF_RESULT res = enc->amf_encoder->ReInit(enc->cx, enc->cy);
if (res != AMF_OK)
throw amf_error("AMFComponent::Init failed", res);
return true;
} catch (const amf_error &err) {
amf_base *enc = (amf_base *)data;
error("%s: %s: %ls", __FUNCTION__, err.str,
amf_trace->GetResultText(err.res));
return false;
}
static bool amf_av1_init(void *data, obs_data_t *settings)
{
amf_base *enc = (amf_base *)data;
int64_t bitrate = obs_data_get_int(settings, "bitrate");
int64_t qp = obs_data_get_int(settings, "cqp");
const char *preset = obs_data_get_string(settings, "preset");
const char *profile = obs_data_get_string(settings, "profile");
const char *rc_str = obs_data_get_string(settings, "rate_control");
int rc = get_av1_rate_control(rc_str);
set_av1_property(enc, RATE_CONTROL_METHOD, rc);
amf_av1_update_data(enc, rc, bitrate * 1000, qp);
set_av1_property(enc, ENFORCE_HRD, true);
int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec");
int gop_size = (keyint_sec) ? keyint_sec * enc->fps_num / enc->fps_den
: 250;
set_av1_property(enc, GOP_SIZE, gop_size);
const char *ffmpeg_opts = obs_data_get_string(settings, "ffmpeg_opts");
if (ffmpeg_opts && *ffmpeg_opts) {
struct obs_options opts = obs_parse_options(ffmpeg_opts);
for (size_t i = 0; i < opts.count; i++) {
amf_apply_opt(enc, &opts.options[i]);
}
obs_free_options(opts);
}
check_preset_compatibility(enc, preset);
if (!ffmpeg_opts || !*ffmpeg_opts)
ffmpeg_opts = "(none)";
info("settings:\n"
"\trate_control: %s\n"
"\tbitrate: %d\n"
"\tcqp: %d\n"
"\tkeyint: %d\n"
"\tpreset: %s\n"
"\tprofile: %s\n"
"\twidth: %d\n"
"\theight: %d\n"
"\tparams: %s",
rc_str, bitrate, qp, gop_size, preset, profile, enc->cx, enc->cy,
ffmpeg_opts);
return true;
}
static void amf_av1_create_internal(amf_base *enc, obs_data_t *settings)
{
enc->codec = amf_codec_type::AV1;
if (!amf_create_encoder(enc))
throw "Failed to create encoder";
AMFCapsPtr caps;
AMF_RESULT res = enc->amf_encoder->GetCaps(&caps);
if (res == AMF_OK) {
caps->GetProperty(AMF_VIDEO_ENCODER_AV1_CAP_MAX_THROUGHPUT,
&enc->max_throughput);
}
const bool is10bit = enc->amf_format == AMF_SURFACE_P010;
const char *preset = obs_data_get_string(settings, "preset");
set_av1_property(enc, FRAMESIZE, AMFConstructSize(enc->cx, enc->cy));
set_av1_property(enc, USAGE, AMF_VIDEO_ENCODER_USAGE_TRANSCODING);
set_av1_property(enc, ALIGNMENT_MODE,
AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_NO_RESTRICTIONS);
set_av1_property(enc, QUALITY_PRESET, get_av1_preset(enc, preset));
set_av1_property(enc, COLOR_BIT_DEPTH,
is10bit ? AMF_COLOR_BIT_DEPTH_10
: AMF_COLOR_BIT_DEPTH_8);
set_av1_property(enc, PROFILE, get_av1_profile(settings));
set_av1_property(enc, ENCODING_LATENCY_MODE,
AMF_VIDEO_ENCODER_AV1_ENCODING_LATENCY_MODE_NONE);
// set_av1_property(enc, RATE_CONTROL_PREENCODE, true);
set_av1_property(enc, OUTPUT_COLOR_PROFILE, enc->amf_color_profile);
set_av1_property(enc, OUTPUT_TRANSFER_CHARACTERISTIC,
enc->amf_characteristic);
set_av1_property(enc, OUTPUT_COLOR_PRIMARIES, enc->amf_primaries);
amf_av1_init(enc, settings);
res = enc->amf_encoder->Init(enc->amf_format, enc->cx, enc->cy);
if (res != AMF_OK)
throw amf_error("AMFComponent::Init failed", res);
set_av1_property(enc, FRAMERATE, enc->amf_frame_rate);
AMFVariant p;
res = enc->amf_encoder->GetProperty(AMF_VIDEO_ENCODER_AV1_EXTRA_DATA,
&p);
if (res == AMF_OK && p.type == AMF_VARIANT_INTERFACE)
enc->header = AMFBufferPtr(p.pInterface);
}
static void *amf_av1_create_texencode(obs_data_t *settings,
obs_encoder_t *encoder)
try {
check_texture_encode_capability(encoder, amf_codec_type::AV1);
std::unique_ptr<amf_texencode> enc = std::make_unique<amf_texencode>();
enc->encoder = encoder;
enc->encoder_str = "texture-amf-av1";
if (!amf_init_d3d11(enc.get()))
throw "Failed to create D3D11";
amf_av1_create_internal(enc.get(), settings);
return enc.release();
} catch (const amf_error &err) {
blog(LOG_ERROR, "[texture-amf-av1] %s: %s: %ls", __FUNCTION__, err.str,
amf_trace->GetResultText(err.res));
return obs_encoder_create_rerouted(encoder, "av1_fallback_amf");
} catch (const char *err) {
blog(LOG_ERROR, "[texture-amf-av1] %s: %s", __FUNCTION__, err);
return obs_encoder_create_rerouted(encoder, "av1_fallback_amf");
}
static void *amf_av1_create_fallback(obs_data_t *settings,
obs_encoder_t *encoder)
try {
std::unique_ptr<amf_fallback> enc = std::make_unique<amf_fallback>();
enc->encoder = encoder;
enc->encoder_str = "fallback-amf-av1";
video_t *video = obs_encoder_video(encoder);
const struct video_output_info *voi = video_output_get_info(video);
switch (voi->format) {
case VIDEO_FORMAT_I010:
case VIDEO_FORMAT_P010: {
break;
}
default:
switch (voi->colorspace) {
case VIDEO_CS_2100_PQ:
case VIDEO_CS_2100_HLG: {
const char *const text =
obs_module_text("AMF.8bitUnsupportedHdr");
obs_encoder_set_last_error(encoder, text);
throw text;
}
}
}
amf_av1_create_internal(enc.get(), settings);
return enc.release();
} catch (const amf_error &err) {
blog(LOG_ERROR, "[fallback-amf-av1] %s: %s: %ls", __FUNCTION__, err.str,
amf_trace->GetResultText(err.res));
return nullptr;
} catch (const char *err) {
blog(LOG_ERROR, "[fallback-amf-av1] %s: %s", __FUNCTION__, err);
return nullptr;
}
static void amf_av1_defaults(obs_data_t *settings)
{
obs_data_set_default_int(settings, "bitrate", 2500);
obs_data_set_default_int(settings, "cqp", 7);
obs_data_set_default_string(settings, "rate_control", "CBR");
obs_data_set_default_string(settings, "preset", "quality");
obs_data_set_default_string(settings, "profile", "high");
}
static void register_av1()
{
struct obs_encoder_info amf_encoder_info = {};
amf_encoder_info.id = "av1_texture_amf";
amf_encoder_info.type = OBS_ENCODER_VIDEO;
amf_encoder_info.codec = "av1";
amf_encoder_info.get_name = amf_av1_get_name;
amf_encoder_info.create = amf_av1_create_texencode;
amf_encoder_info.destroy = amf_destroy;
amf_encoder_info.update = amf_av1_update;
amf_encoder_info.encode_texture = amf_encode_tex;
amf_encoder_info.get_defaults = amf_av1_defaults;
amf_encoder_info.get_properties = amf_av1_properties;
amf_encoder_info.get_extra_data = amf_extra_data;
amf_encoder_info.caps = OBS_ENCODER_CAP_PASS_TEXTURE |
OBS_ENCODER_CAP_DYN_BITRATE;
obs_register_encoder(&amf_encoder_info);
amf_encoder_info.id = "av1_fallback_amf";
amf_encoder_info.caps = OBS_ENCODER_CAP_INTERNAL |
OBS_ENCODER_CAP_DYN_BITRATE;
amf_encoder_info.encode_texture = nullptr;
amf_encoder_info.create = amf_av1_create_fallback;
amf_encoder_info.encode = amf_encode_fallback;
amf_encoder_info.get_video_info = av1_video_info_fallback;
obs_register_encoder(&amf_encoder_info);
}
/* ========================================================================= */
/* Global Stuff */
@@ -1694,7 +2140,7 @@ try {
FreeLibrary(amf_module_test);
/* ----------------------------------- */
/* Check for AVC/HEVC support */
/* Check for supported codecs */
BPtr<char> test_exe = os_get_executable_path_ptr("obs-amf-test.exe");
std::string caps_str;
@@ -1731,6 +2177,7 @@ try {
uint32_t adapter_count = (uint32_t)config_num_sections(config);
bool avc_supported = false;
bool hevc_supported = false;
bool av1_supported = false;
for (uint32_t i = 0; i < adapter_count; i++) {
std::string section = std::to_string(i);
@@ -1742,13 +2189,16 @@ try {
"supports_avc");
info.supports_hevc = config_get_bool(config, section.c_str(),
"supports_hevc");
info.supports_av1 = config_get_bool(config, section.c_str(),
"supports_av1");
avc_supported |= info.supports_avc;
hevc_supported |= info.supports_hevc;
av1_supported |= info.supports_av1;
}
if (!avc_supported && !hevc_supported)
throw "Neither AVC nor HEVC are supported by any devices";
if (!avc_supported && !hevc_supported && !av1_supported)
throw "Neither AVC, HEVC, nor AV1 are supported by any devices";
/* ----------------------------------- */
/* Init AMF */
@@ -1793,6 +2243,8 @@ try {
if (hevc_supported)
register_hevc();
#endif
if (av1_supported)
register_av1();
} catch (const std::string &str) {
/* doing debug here because string exceptions indicate the user is