From 975b3720ba5948a0e12b83ccfb7b902395b53ef0 Mon Sep 17 00:00:00 2001 From: Focus Luo Date: Fri, 14 Jun 2024 00:33:11 -0700 Subject: [PATCH] [stringapi] add stringapi support Signed-off-by: Focus Luo Signed-off-by: U. Artie Eoff --- .slashrc | 4 + lib/caps/ADL/info | 1 + lib/caps/ATSM/info | 1 + lib/caps/DG1/info | 1 + lib/caps/DG2/info | 1 + lib/caps/MTL/info | 1 + lib/caps/RKL/info | 1 + lib/caps/RPL/info | 1 + lib/caps/SG1/info | 1 + lib/caps/TGL/info | 1 + lib/ffmpeg/qsv/encoder.py | 8 ++ lib/mfx/api.py | 141 ++++++++++++++++++++++++++++ lib/platform.py | 7 ++ lib/string_api.py | 167 +++++++++++++++++++++++++++++++++ test/ffmpeg-qsv/encode/av1.py | 44 +++++++++ test/ffmpeg-qsv/encode/avc.py | 43 +++++++++ test/ffmpeg-qsv/encode/hevc.py | 44 +++++++++ 17 files changed, 467 insertions(+) create mode 100644 lib/mfx/api.py create mode 100644 lib/string_api.py diff --git a/.slashrc b/.slashrc index eedec6fe..5ee0ed2d 100644 --- a/.slashrc +++ b/.slashrc @@ -209,6 +209,10 @@ class MediaPlugin(slash.plugins.PluginInterface): from lib.platform import info return info()["gpu"]["gen"] + def _get_platform_stringapi_enable(self): + from lib.platform import info + return info()["stringapi"]["enable"] + def _get_call_timeout(self): if self.test_call_timeout > 0: return self.test_call_timeout diff --git a/lib/caps/ADL/info b/lib/caps/ADL/info index 50a3a9da..f6c485f3 100644 --- a/lib/caps/ADL/info +++ b/lib/caps/ADL/info @@ -10,4 +10,5 @@ info = dict( gpu = dict(gen = 12.2), + stringapi = dict(enable = True), ) diff --git a/lib/caps/ATSM/info b/lib/caps/ATSM/info index a809063f..6da6885c 100644 --- a/lib/caps/ATSM/info +++ b/lib/caps/ATSM/info @@ -10,4 +10,5 @@ info = dict( gpu = dict(gen = 12.7), + stringapi = dict(enable = True), ) diff --git a/lib/caps/DG1/info b/lib/caps/DG1/info index 1795cad0..559686b4 100644 --- a/lib/caps/DG1/info +++ b/lib/caps/DG1/info @@ -10,4 +10,5 @@ info = dict( gpu = dict(gen = 12), + stringapi = dict(enable = True), ) diff --git a/lib/caps/DG2/info b/lib/caps/DG2/info index a809063f..6da6885c 100644 --- a/lib/caps/DG2/info +++ b/lib/caps/DG2/info @@ -10,4 +10,5 @@ info = dict( gpu = dict(gen = 12.7), + stringapi = dict(enable = True), ) diff --git a/lib/caps/MTL/info b/lib/caps/MTL/info index 393c060f..ec01101a 100644 --- a/lib/caps/MTL/info +++ b/lib/caps/MTL/info @@ -10,4 +10,5 @@ info = dict( gpu = dict(gen = 13), + stringapi = dict(enable = True), ) diff --git a/lib/caps/RKL/info b/lib/caps/RKL/info index 1795cad0..559686b4 100644 --- a/lib/caps/RKL/info +++ b/lib/caps/RKL/info @@ -10,4 +10,5 @@ info = dict( gpu = dict(gen = 12), + stringapi = dict(enable = True), ) diff --git a/lib/caps/RPL/info b/lib/caps/RPL/info index 6cf53b6f..289b4971 100644 --- a/lib/caps/RPL/info +++ b/lib/caps/RPL/info @@ -10,4 +10,5 @@ info = dict( gpu = dict(gen = 12.2), + stringapi = dict(enable = True), ) diff --git a/lib/caps/SG1/info b/lib/caps/SG1/info index 1795cad0..559686b4 100644 --- a/lib/caps/SG1/info +++ b/lib/caps/SG1/info @@ -10,4 +10,5 @@ info = dict( gpu = dict(gen = 12), + stringapi = dict(enable = True), ) diff --git a/lib/caps/TGL/info b/lib/caps/TGL/info index 1795cad0..559686b4 100644 --- a/lib/caps/TGL/info +++ b/lib/caps/TGL/info @@ -10,4 +10,5 @@ info = dict( gpu = dict(gen = 12), + stringapi = dict(enable = True), ) diff --git a/lib/ffmpeg/qsv/encoder.py b/lib/ffmpeg/qsv/encoder.py index 7af0bea0..2891f83d 100644 --- a/lib/ffmpeg/qsv/encoder.py +++ b/lib/ffmpeg/qsv/encoder.py @@ -15,6 +15,7 @@ from ....lib.common import mapRangeInt, get_media, call, exe2os from ....lib.codecs import Codec from ....lib.formats import PixelFormat +from ....lib.mfx.api import StringAPI class Encoder(FFEncoder): hwaccel = property(lambda s: "qsv") @@ -65,6 +66,13 @@ def encparams(self): f"{self.iqoffset}{self.bqoffset}" ) +# NOTE: Inherit from the StringAPI class first so that it overrides the +# Encoder class +class StringAPIEncoder(StringAPI, Encoder): + @property + def encparams(self): + return f" -qsv_params '{super().encparams}'" + @slash.requires(*have_ffmpeg_hwaccel("qsv")) @slash.requires(using_compatible_driver) class EncoderTest(BaseEncoderTest): diff --git a/lib/mfx/api.py b/lib/mfx/api.py new file mode 100644 index 00000000..04e3780b --- /dev/null +++ b/lib/mfx/api.py @@ -0,0 +1,141 @@ +from ...lib.codecs import Codec +from ...lib.common import memoize +from ...lib.properties import PropertyHandler + +# TODO: move string_api enums to this file +# NOTE/FIXME: these enums need to derive from IntEnum, not Enum +from ...lib.string_api import CodecProfile as MfxCodecProfile +from ...lib.string_api import CodecLevel as MfxCodecLevel +from ...lib.string_api import RateControlMethod as MfxRateControlMethod + +class StringAPI(PropertyHandler): + level = property(lambda s: s.ifprop("level", "CodecLevel={level}")) + gop = property(lambda s: s.ifprop("gop", "GopPicSize={gop}")) + bframes = property(lambda s: s.ifprop("bframes", "GopRefDist={bframes}")) + slices = property(lambda s: s.ifprop("slices", "NumSlice={slices}")) + minrate = property(lambda s: s.ifprop("minrate", "TargetKbps={minrate}")) + maxrate = property(lambda s: s.ifprop("maxrate", "MaxKbps={maxrate}")) + refs = property(lambda s: s.ifprop("refs", "NumRefFrame={refs}")) + ladepth = property(lambda s: s.ifprop("ladepth", "LookAheadDepth={ladepth}")) + extbrc = property(lambda s: s.ifprop("extbrc", "ExtBRC={extbrc}")) + ldb = property(lambda s: s.ifprop("ldb", "mfxExtCodingOption3.LowDelayBRC={ldb}")) + strict = property(lambda s: s.ifprop("strict", "GopOptFlag={strict}")) + pict = property(lambda s: s.ifprop("vpict", "mfxExtCodingOption.PicTimingSEI=0")) + quality = property(lambda s: s.ifprop("quality", "TargetUsage={quality}")) + lowpower = property(lambda s: s.ifprop("lowpower", "LowPower={lowpower}")) + tilecols = property(lambda s: s.ifprop("tilecols", "mfxExtAV1TileParam.NumTileColumns={tilecols}")) + tilerows = property(lambda s: s.ifprop("tilerows", "mfxExtAV1TileParam.NumTileRows={tilerows}")) + maxframesize = property(lambda s: s.ifprop("maxframesize", "MaxSliceSize={maxframesize}")) + + @property + def profile(self): + def inner(profile): + return f"CodecProfile={self.map_profile(self.codec, self.props['profile'])}" + return self.ifprop("profile", inner) + + @property + def rcmode(self): + return f"RateControlMethod={self.map_rcmode(self.props['rcmode'])}" + + @property + def level(self): + def inner(level): + # TODO: need to define map_level + return f"CodecLevel={self.map_level(self.props['level'])}" + return self.ifprop("level", inner) + + @property + def qp(self): + def inner(qp): + rcmode = self.props["rcmode"].upper() + mqp = qp + if self.codec in [Codec.MPEG2]: + mqp = mapRangeInt(qp, [0, 100], [1, 51]) + elif self.codec in [Codec.AV1] and "ICQ" == rcmode: + mqp = mapRangeInt(qp, [0, 255], [1, 51]) + elif self.codec in [Codec.HEVC] and "QVBR" == rcmode: + mqp = mapRangeInt(qp, [0, 255], [1, 51]) + return f"QPI={mqp}:QPP={mqp}:QPB={mqp}" + return self.ifprop("qp", inner) + + @property + def encparams(self): + params = [ + self.profile, self.rcmode, self.qp, self.level, self.gop, self.bframes, + self.slices, self.minrate, self.maxrate, self.refs, self.ladepth, + self.extbrc, self.ldb, self.strict, self.pict, self.quality, self.lowpower, + self.tilecols, self.tilerows, self.maxframesize, + ] + return ':'.join(v for v in params if len(v) != 0) + + @classmethod + @memoize + def map_profile(cls, codec, profile): + # TODO: we could move this method to the enum class as "lookup" + # then call MfxCodecProfile.lookup(codec, profile) + return { + Codec.AVC : { + "high" : MfxCodecProfile.MFX_PROFILE_AVC_HIGH, + "main" : MfxCodecProfile.MFX_PROFILE_AVC_MAIN, + "baseline" : MfxCodecProfile.MFX_PROFILE_AVC_BASELINE, + "unknown" : MfxCodecProfile.MFX_PROFILE_UNKNOWN + }, + Codec.HEVC : { + "main" : MfxCodecProfile.MFX_PROFILE_HEVC_MAIN, + "main444" : MfxCodecProfile.MFX_PROFILE_HEVC_REXT, + "scc" : MfxCodecProfile.MFX_PROFILE_HEVC_SCC, + "scc-444" : MfxCodecProfile.MFX_PROFILE_HEVC_SCC, + "mainsp" : MfxCodecProfile.MFX_PROFILE_HEVC_MAINSP, + "main10" : MfxCodecProfile.MFX_PROFILE_HEVC_MAIN10, + "main10sp" : MfxCodecProfile.MFX_PROFILE_HEVC_MAINSP, + "main444-10" : MfxCodecProfile.MFX_PROFILE_HEVC_REXT, + "unknown" : MfxCodecProfile.MFX_PROFILE_UNKNOWN + }, + Codec.AV1 : { + "main" : MfxCodecProfile.MFX_PROFILE_AV1_MAIN, + }, + Codec.VP9 : { + "profile0" : MfxCodecProfile.MFX_PROFILE_VP9_0, + "profile1" : MfxCodecProfile.MFX_PROFILE_VP9_1, + "profile2" : MfxCodecProfile.MFX_PROFILE_VP9_2, + "profile3" : MfxCodecProfile.MFX_PROFILE_VP9_3 + }, + }[codec][profile] + + @classmethod + @memoize + def map_rcmode(cls, rcmode): + # TODO: we could move this method to the enum class as "lookup" + # then call MfxRateControlMethod.lookup(rcmode) + return { + "CQP" : MfxRateControlMethod.MFX_RATECONTROL_CQP, + "CBR" : MfxRateControlMethod.MFX_RATECONTROL_CBR, + "VBR" : MfxRateControlMethod.MFX_RATECONTROL_VBR, + "ICQ" : MfxRateControlMethod.MFX_RATECONTROL_ICQ, + }[rcmode.upper()] + +# Example: +# +# +# +# # NOTE: Inherit from the StringAPI class first so that it overrides the +# # Encoder class +# from ....lib.mfx.api import StringAPI +# class StringAPIEncoder(StringAPI, Encoder): +# @property +# def encparams(self): +# return f" -qsv_params '{super().encparams}'" +# +# +# +# from ....lib.ffmpeg.qsv.encoder import StringAPIEncoder +# class cqp(HEVC8EncoderTest): +# ... +# @slash.requires(*have_string_api) # TODO: define have_string_api +# @slash.parametrize(*gen_hevc_cqp_parameters(spec, ['main'])) +# def test_strapi(self, case, gop, slices, bframes, qp, quality, profile): +# self.EncoderClass = StringAPIEncoder +# self.init(spec, case, gop, slices, bframes, qp, quality, profile) +# self.encode() +# +# diff --git a/lib/platform.py b/lib/platform.py index 2d2bcc94..7f4a61ca 100644 --- a/lib/platform.py +++ b/lib/platform.py @@ -85,6 +85,13 @@ def have_caps(*args): ) return get_caps(*args) is not None, failmsg +@memoize +def have_string_api(): + from .common import get_media + has_strapi = False + has_strapi = get_media()._get_platform_stringapi_enable() + return has_strapi is not None, False + @memoize def load_capsinfo_file(infofile): namespace = dict() diff --git a/lib/string_api.py b/lib/string_api.py new file mode 100644 index 00000000..9fe67c9d --- /dev/null +++ b/lib/string_api.py @@ -0,0 +1,167 @@ +from enum import IntEnum, unique + +#define come from _install/include/vpl/mfxstructures.h + +class CodecProfile(IntEnum): + MFX_PROFILE_UNKNOWN =0 #/*!< Unspecified profile. */ + + #/* Combined with H.264 profile these flags impose additional constrains. See H.264 specification for the list of constrains. */ + MFX_PROFILE_AVC_CONSTRAINT_SET0 = (0x100 << 0) + MFX_PROFILE_AVC_CONSTRAINT_SET1 = (0x100 << 1) + MFX_PROFILE_AVC_CONSTRAINT_SET2 = (0x100 << 2) + MFX_PROFILE_AVC_CONSTRAINT_SET3 = (0x100 << 3) + MFX_PROFILE_AVC_CONSTRAINT_SET4 = (0x100 << 4) + MFX_PROFILE_AVC_CONSTRAINT_SET5 = (0x100 << 5) + + #/* H.264 Profiles. */ + MFX_PROFILE_AVC_BASELINE =66 + MFX_PROFILE_AVC_MAIN =77 + MFX_PROFILE_AVC_EXTENDED =88 + MFX_PROFILE_AVC_HIGH =100 + MFX_PROFILE_AVC_HIGH10 =110 + MFX_PROFILE_AVC_HIGH_422 =122 + MFX_PROFILE_AVC_CONSTRAINED_BASELINE =MFX_PROFILE_AVC_BASELINE + MFX_PROFILE_AVC_CONSTRAINT_SET1 + MFX_PROFILE_AVC_CONSTRAINED_HIGH =MFX_PROFILE_AVC_HIGH + MFX_PROFILE_AVC_CONSTRAINT_SET4 + MFX_PROFILE_AVC_CONSTRAINT_SET5 + MFX_PROFILE_AVC_PROGRESSIVE_HIGH =MFX_PROFILE_AVC_HIGH + MFX_PROFILE_AVC_CONSTRAINT_SET4 + + #/* HEVC profiles */ + MFX_PROFILE_HEVC_MAIN =1 + MFX_PROFILE_HEVC_MAIN10 =2 + MFX_PROFILE_HEVC_MAINSP =3 + MFX_PROFILE_HEVC_REXT =4 + MFX_PROFILE_HEVC_SCC =9 + + #/* AV1 Profiles */ + MFX_PROFILE_AV1_MAIN = 1 + MFX_PROFILE_AV1_HIGH = 2 + MFX_PROFILE_AV1_PRO = 3 + + #/* VP9 Profiles */ + MFX_PROFILE_VP9_0 = 1 + MFX_PROFILE_VP9_1 = 2 + MFX_PROFILE_VP9_2 = 3 + MFX_PROFILE_VP9_3 = 4 + +class CodecLevel(IntEnum): + MFX_LEVEL_UNKNOWN =0 #/*!< Unspecified level. */ + #/* H.264 level 1-1.3 */ + MFX_LEVEL_AVC_1 =10 + MFX_LEVEL_AVC_1b =9 + MFX_LEVEL_AVC_11 =11 + MFX_LEVEL_AVC_12 =12 + MFX_LEVEL_AVC_13 =13 + #/* H.264 level 2-2.2 */ + MFX_LEVEL_AVC_2 =20 + MFX_LEVEL_AVC_21 =21 + MFX_LEVEL_AVC_22 =22 + #/* H.264 level 3-3.2 */ + MFX_LEVEL_AVC_3 =30 + MFX_LEVEL_AVC_31 =31 + MFX_LEVEL_AVC_32 =32 + #/* H.264 level 4-4.2 */ + MFX_LEVEL_AVC_4 =40 + MFX_LEVEL_AVC_41 =41 + MFX_LEVEL_AVC_42 =42 + #/* H.264 level 5-5.2 */ + MFX_LEVEL_AVC_5 =50 + MFX_LEVEL_AVC_51 =51 + MFX_LEVEL_AVC_52 =52 + #/* H.264 level 6-6.2 */ + MFX_LEVEL_AVC_6 =60 + MFX_LEVEL_AVC_61 =61 + MFX_LEVEL_AVC_62 =62 + + #/* HEVC levels */ + MFX_LEVEL_HEVC_1 = 10 + MFX_LEVEL_HEVC_2 = 20 + MFX_LEVEL_HEVC_21 = 21 + MFX_LEVEL_HEVC_3 = 30 + MFX_LEVEL_HEVC_31 = 31 + MFX_LEVEL_HEVC_4 = 40 + MFX_LEVEL_HEVC_41 = 41 + MFX_LEVEL_HEVC_5 = 50 + MFX_LEVEL_HEVC_51 = 51 + MFX_LEVEL_HEVC_52 = 52 + MFX_LEVEL_HEVC_6 = 60 + MFX_LEVEL_HEVC_61 = 61 + MFX_LEVEL_HEVC_62 = 62 + + #/* AV1 Levels */ + MFX_LEVEL_AV1_2 = 20 + MFX_LEVEL_AV1_21 = 21 + MFX_LEVEL_AV1_22 = 22 + MFX_LEVEL_AV1_23 = 23 + MFX_LEVEL_AV1_3 = 30 + MFX_LEVEL_AV1_31 = 31 + MFX_LEVEL_AV1_32 = 32 + MFX_LEVEL_AV1_33 = 33 + MFX_LEVEL_AV1_4 = 40 + MFX_LEVEL_AV1_41 = 41 + MFX_LEVEL_AV1_42 = 42 + MFX_LEVEL_AV1_43 = 43 + MFX_LEVEL_AV1_5 = 50 + MFX_LEVEL_AV1_51 = 51 + MFX_LEVEL_AV1_52 = 52 + MFX_LEVEL_AV1_53 = 53 + MFX_LEVEL_AV1_6 = 60 + MFX_LEVEL_AV1_61 = 61 + MFX_LEVEL_AV1_62 = 62 + MFX_LEVEL_AV1_63 = 63 + MFX_LEVEL_AV1_7 = 70 + MFX_LEVEL_AV1_71 = 71 + MFX_LEVEL_AV1_72 = 72 + MFX_LEVEL_AV1_73 = 73 + + +class RateControlMethod(IntEnum): +#/*! The RateControlMethod enumerator itemizes bitrate control methods. */ + MFX_RATECONTROL_CBR =1 #/*!< Use the constant bitrate control algorithm. */ + MFX_RATECONTROL_VBR =2 #/*!< Use the variable bitrate control algorithm. */ + MFX_RATECONTROL_CQP =3 #/*!< Use the constant quantization parameter algorithm. */ + MFX_RATECONTROL_AVBR =4 #/*!< Use the average variable bitrate control algorithm. */ + MFX_RATECONTROL_RESERVED1 =5 + MFX_RATECONTROL_RESERVED2 =6 + MFX_RATECONTROL_RESERVED3 =100 + MFX_RATECONTROL_RESERVED4 =7 + #/*! + # Use the VBR algorithm with look ahead. It is a special bitrate control mode in the AVC encoder that has been designed + # to improve encoding quality. It works by performing extensive analysis of several dozen frames before the actual encoding and as a side + # effect significantly increases encoding delay and memory consumption. + + # The only available rate control parameter in this mode is mfxInfoMFX::TargetKbps. Two other parameters, MaxKbps and InitialDelayInKB, + # are ignored. To control LA depth the application can use mfxExtCodingOption2::LookAheadDepth parameter. + + # This method is not HRD compliant. + #*/ + MFX_RATECONTROL_LA =8 + #/*! + # Use the Intelligent Constant Quality algorithm. This algorithm improves subjective video quality of encoded stream. Depending on content, + # it may or may not decrease objective video quality. Only one control parameter is used - quality factor, specified by mfxInfoMFX::ICQQuality. + #*/ + MFX_RATECONTROL_ICQ =9 + #/*! + # Use the Video Conferencing Mode algorithm. This algorithm is similar to the VBR and uses the same set of parameters mfxInfoMFX::InitialDelayInKB, + # TargetKbpsandMaxKbps. It is tuned for IPPP GOP pattern and streams with strong temporal correlation between frames. + # It produces better objective and subjective video quality in these conditions than other bitrate control algorithms. + # It does not support interlaced content, B-frames and produced stream is not HRD compliant. + #*/ + MFX_RATECONTROL_VCM =10 + #/*! + # Use Intelligent Constant Quality algorithm with look ahead. Quality factor is specified by mfxInfoMFX::ICQQuality. + # To control LA depth the application can use mfxExtCodingOption2::LookAheadDepth parameter. + # + # This method is not HRD compliant. + #*/ + MFX_RATECONTROL_LA_ICQ =11 + #/*! + # MFX_RATECONTROL_LA_EXT has been removed + #*/ + + #/*! Use HRD compliant look ahead rate control algorithm. */ + MFX_RATECONTROL_LA_HRD =13 + #/*! + # Use the variable bitrate control algorithm with constant quality. This algorithm trying to achieve the target subjective quality with + # the minimum number of bits, while the bitrate constraint and HRD compliance are satisfied. It uses the same set of parameters + # as VBR and quality factor specified by mfxExtCodingOption3::QVBRQuality. + #*/ + MFX_RATECONTROL_QVBR =14 diff --git a/test/ffmpeg-qsv/encode/av1.py b/test/ffmpeg-qsv/encode/av1.py index 3fd5cf15..0aca47ca 100644 --- a/test/ffmpeg-qsv/encode/av1.py +++ b/test/ffmpeg-qsv/encode/av1.py @@ -7,6 +7,7 @@ from ....lib import * from ....lib.ffmpeg.qsv.util import * from ....lib.ffmpeg.qsv.encoder import AV1EncoderLPTest, AV1EncoderTest +from ....lib.ffmpeg.qsv.encoder import StringAPIEncoder spec = load_test_spec("av1", "encode", "8bit") spec_r2r = load_test_spec("av1", "encode", "8bit", "r2r") @@ -37,6 +38,13 @@ def test_r2r(self, case, gop, bframes, tilecols, tilerows, qp, quality, profile) vars(self).setdefault("r2r", 5) self.encode() + @slash.requires(have_string_api) + @slash.parametrize(*gen_av1_cqp_parameters(spec)) + def test_strapi(self, case, gop, bframes, tilecols, tilerows, qp, quality, profile): + self.EncoderClass = StringAPIEncoder + self.init(spec, case, gop, bframes, tilecols, tilerows, qp, quality, profile) + self.encode() + class icq(AV1EncoderTest): def init(self, tspec, case, gop, bframes, tilecols, tilerows,qp, quality, profile): vars(self).update(tspec[case].copy()) @@ -92,6 +100,13 @@ def test_r2r(self, case, gop, bframes, tilecols, tilerows, bitrate, quality, fps vars(self).setdefault("r2r", 5) self.encode() + @slash.requires(have_string_api) + @slash.parametrize(*gen_av1_cbr_parameters(spec)) + def test_strapi(self, case, gop, bframes, tilecols, tilerows, bitrate, quality, fps, profile): + self.EncoderClass = StringAPIEncoder + self.init(spec, case, gop, bframes, tilecols, tilerows, bitrate, fps, quality, profile) + self.encode() + class vbr(AV1EncoderTest): def init(self, tspec, case, gop, bframes, tilecols, tilerows, bitrate, fps, quality, profile): vars(self).update(tspec[case].copy()) @@ -122,6 +137,13 @@ def test_r2r(self, case, gop, bframes, tilecols, tilerows, bitrate, fps, quality vars(self).setdefault("r2r", 5) self.encode() + @slash.requires(have_string_api) + @slash.parametrize(*gen_av1_vbr_parameters(spec)) + def test_strapi(self, case, gop, bframes, tilecols, tilerows, bitrate, fps, quality, profile): + self.EncoderClass = StringAPIEncoder + self.init(spec, case, gop, bframes, tilecols, tilerows, bitrate, fps, quality, profile) + self.encode() + class cqp_lp(AV1EncoderLPTest): def init(self, tspec, case, gop, bframes, tilecols, tilerows,qp, quality, profile): vars(self).update(tspec[case].copy()) @@ -148,6 +170,13 @@ def test_r2r(self, case, gop, bframes, tilecols, tilerows, qp, quality, profile) vars(self).setdefault("r2r", 5) self.encode() + @slash.requires(have_string_api) + @slash.parametrize(*gen_av1_cqp_lp_parameters(spec)) + def test_strapi(self, case, gop, bframes, tilecols, tilerows, qp, quality, profile): + self.EncoderClass = StringAPIEncoder + self.init(spec, case, gop, bframes, tilecols, tilerows, qp, quality, profile) + self.encode() + class icq_lp(AV1EncoderLPTest): def init(self, tspec, case, gop, bframes, tilecols, tilerows,qp, quality, profile): vars(self).update(tspec[case].copy()) @@ -203,6 +232,13 @@ def test_r2r(self, case, gop, bframes, tilecols, tilerows, bitrate, quality, fps vars(self).setdefault("r2r", 5) self.encode() + @slash.requires(have_string_api) + @slash.parametrize(*gen_av1_cbr_lp_parameters(spec)) + def test_strapi(self, case, gop, bframes, tilecols, tilerows, bitrate, quality, fps, profile): + self.EncoderClass = StringAPIEncoder + self.init(spec, case, gop, bframes, tilecols, tilerows, bitrate, fps, quality, profile) + self.encode() + class vbr_lp(AV1EncoderLPTest): def init(self, tspec, case, gop, bframes, tilecols, tilerows, bitrate, fps, quality, profile): vars(self).update(tspec[case].copy()) @@ -232,3 +268,11 @@ def test_r2r(self, case, gop, bframes, tilecols, tilerows, bitrate, fps, quality self.init(spec_r2r, case, gop, bframes, tilecols, tilerows, bitrate, fps, quality, profile) vars(self).setdefault("r2r", 5) self.encode() + + @slash.requires(have_string_api) + @slash.parametrize(*gen_av1_vbr_lp_parameters(spec)) + def test_strapi(self, case, gop, bframes, tilecols, tilerows, bitrate, fps, quality, profile): + self.EncoderClass = StringAPIEncoder + self.init(spec, case, gop, bframes, tilecols, tilerows, bitrate, fps, quality, profile) + self.encode() + diff --git a/test/ffmpeg-qsv/encode/avc.py b/test/ffmpeg-qsv/encode/avc.py index e612a45d..5d0bd435 100755 --- a/test/ffmpeg-qsv/encode/avc.py +++ b/test/ffmpeg-qsv/encode/avc.py @@ -7,6 +7,7 @@ from ....lib import * from ....lib.ffmpeg.qsv.util import * from ....lib.ffmpeg.qsv.encoder import AVCEncoderTest, AVCEncoderLPTest +from ....lib.ffmpeg.qsv.encoder import StringAPIEncoder spec = load_test_spec("avc", "encode") spec_r2r = load_test_spec("avc", "encode", "r2r") @@ -36,6 +37,13 @@ def test_r2r(self, case, gop, slices, bframes, qp, quality, profile): vars(self).setdefault("r2r", 5) self.encode() + @slash.requires(have_string_api) + @slash.parametrize(*gen_avc_cqp_parameters(spec, ['high', 'main', 'baseline'])) + def test_strapi(self, case, gop, slices, bframes, qp, quality, profile): + self.EncoderClass = StringAPIEncoder + self.init(spec, case, gop, slices, bframes, qp, quality, profile) + self.encode() + class cqp_lp(AVCEncoderLPTest): def init(self, tspec, case, gop, slices, bframes, qp, quality, profile): vars(self).update(tspec[case].copy()) @@ -61,6 +69,13 @@ def test_r2r(self, case, gop, slices, bframes, qp, quality, profile): vars(self).setdefault("r2r", 5) self.encode() + @slash.requires(have_string_api) + @slash.parametrize(*gen_avc_cqp_lp_parameters(spec, ['high', 'main'])) + def test_strapi(self, case, gop, slices, bframes, qp, quality, profile): + self.EncoderClass = StringAPIEncoder + self.init(spec, case, gop, slices, bframes, qp, quality, profile) + self.encode() + class cbr(AVCEncoderTest): def init(self, tspec, case, gop, slices, bframes, bitrate, fps, profile): vars(self).update(tspec[case].copy()) @@ -88,6 +103,13 @@ def test_r2r(self, case, gop, slices, bframes, bitrate, fps, profile): vars(self).setdefault("r2r", 5) self.encode() + @slash.requires(have_string_api) + @slash.parametrize(*gen_avc_cbr_parameters(spec, ['high', 'main', 'baseline'])) + def test_strapi(self, case, gop, slices, bframes, bitrate, fps, profile): + self.EncoderClass = StringAPIEncoder + self.init(spec, case, gop, slices, bframes, bitrate, fps, profile) + self.encode() + class cbr_lp(AVCEncoderLPTest): def init(self, tspec, case, gop, slices, bframes, bitrate, fps, profile): vars(self).update(tspec[case].copy()) @@ -115,6 +137,13 @@ def test_r2r(self, case, gop, slices, bframes, bitrate, fps, profile): vars(self).setdefault("r2r", 5) self.encode() + @slash.requires(have_string_api) + @slash.parametrize(*gen_avc_cbr_lp_parameters(spec, ['high', 'main'])) + def test_strapi(self, case, gop, slices, bframes, bitrate, fps, profile): + self.EncoderClass = StringAPIEncoder + self.init(spec, case, gop, slices, bframes, bitrate, fps, profile) + self.encode() + class vbr(AVCEncoderTest): def init(self, tspec, case, gop, slices, bframes, bitrate, fps, quality, refs, profile): vars(self).update(tspec[case].copy()) @@ -144,6 +173,13 @@ def test_r2r(self, case, gop, slices, bframes, bitrate, fps, quality, refs, prof vars(self).setdefault("r2r", 5) self.encode() + @slash.requires(have_string_api) + @slash.parametrize(*gen_avc_vbr_parameters(spec_r2r, ['high', 'main', 'baseline'])) + def test_strapi(self, case, gop, slices, bframes, bitrate, fps, quality, refs, profile): + self.EncoderClass = StringAPIEncoder + self.init(spec, case, gop, slices, bframes, bitrate, fps, quality, refs, profile) + self.encode() + class vbr_lp(AVCEncoderLPTest): def before(self): super().before() @@ -191,6 +227,13 @@ def test_tcbrc(self, case, bitrate, fps, profile): ) self.encode() + @slash.requires(have_string_api) + @slash.parametrize(*gen_avc_vbr_lp_parameters(spec, ['high', 'main'])) + def test_strapi(self, case, gop, slices, bframes, bitrate, fps, quality, refs, profile): + self.EncoderClass = StringAPIEncoder + self.init(spec, case, gop, slices, bframes, bitrate, fps, quality, refs, profile) + self.encode() + # TODO: This can be moved into the vbr test class in a test_la method class vbr_la(AVCEncoderTest): @slash.parametrize(*gen_avc_vbr_la_parameters(spec, ['high', 'main', 'baseline'])) diff --git a/test/ffmpeg-qsv/encode/hevc.py b/test/ffmpeg-qsv/encode/hevc.py index b171d390..e10de30d 100755 --- a/test/ffmpeg-qsv/encode/hevc.py +++ b/test/ffmpeg-qsv/encode/hevc.py @@ -7,6 +7,7 @@ from ....lib import * from ....lib.ffmpeg.qsv.util import * from ....lib.ffmpeg.qsv.encoder import HEVC8EncoderTest, HEVC8EncoderLPTest +from ....lib.ffmpeg.qsv.encoder import StringAPIEncoder spec = load_test_spec("hevc", "encode", "8bit") spec_r2r = load_test_spec("hevc", "encode", "8bit", "r2r") @@ -36,6 +37,14 @@ def test_r2r(self, case, gop, slices, bframes, qp, quality, profile): vars(self).setdefault("r2r", 5) self.encode() + @slash.requires(have_string_api) + @slash.parametrize(*gen_hevc_cqp_parameters(spec, ['main'])) + def test_strapi(self, case, gop, slices, bframes, qp, quality, profile): + self.EncoderClass = StringAPIEncoder + self.init(spec, case, gop, slices, bframes, qp, quality, profile) + self.EncoderClass = StringAPIEncoder + self.encode() + class cqp_lp(HEVC8EncoderLPTest): def init(self, tspec, case, gop, slices, qp, quality, profile): vars(self).update(tspec[case].copy()) @@ -60,6 +69,13 @@ def test_r2r(self, case, gop, slices, qp, quality, profile): vars(self).setdefault("r2r", 5) self.encode() + @slash.requires(have_string_api) + @slash.parametrize(*gen_hevc_cqp_lp_parameters(spec, ['main'])) + def test_strapi(self, case, gop, slices, qp, quality, profile): + self.EncoderClass = StringAPIEncoder + self.init(spec, case, gop, slices, qp, quality, profile) + self.encode() + class cbr(HEVC8EncoderTest): def init(self, tspec, case, gop, slices, bframes, bitrate, fps, profile): vars(self).update(tspec[case].copy()) @@ -87,6 +103,13 @@ def test_r2r(self, case, gop, slices, bframes, bitrate, fps, profile): vars(self).setdefault("r2r", 5) self.encode() + @slash.requires(have_string_api) + @slash.parametrize(*gen_hevc_cbr_parameters(spec, ['main'])) + def test_strapi(self, case, gop, slices, bframes, bitrate, fps, profile): + self.EncoderClass = StringAPIEncoder + self.init(spec, case, gop, slices, bframes, bitrate, fps, profile) + self.encode() + class cbr_lp(HEVC8EncoderLPTest): def init(self, tspec, case, gop, slices, bitrate, fps, profile): vars(self).update(tspec[case].copy()) @@ -113,6 +136,13 @@ def test_r2r(self, case, gop, slices, bitrate, fps, profile): vars(self).setdefault("r2r", 5) self.encode() + @slash.requires(have_string_api) + @slash.parametrize(*gen_hevc_cbr_lp_parameters(spec, ['main'])) + def test_strapi(self, case, gop, slices, bitrate, fps, profile): + self.EncoderClass = StringAPIEncoder + self.init(spec, case, gop, slices, bitrate, fps, profile) + self.encode() + class vbr(HEVC8EncoderTest): def init(self, tspec, case, gop, slices, bframes, bitrate, fps, quality, refs, profile): vars(self).update(tspec[case].copy()) @@ -142,6 +172,13 @@ def test_r2r(self, case, gop, slices, bframes, bitrate, fps, quality, refs, prof vars(self).setdefault("r2r", 5) self.encode() + @slash.requires(have_string_api) + @slash.parametrize(*gen_hevc_vbr_parameters(spec, ['main'])) + def test_strapi(self, case, gop, slices, bframes, bitrate, fps, quality, refs, profile): + self.EncoderClass = StringAPIEncoder + self.init(spec, case, gop, slices, bframes, bitrate, fps, quality, refs, profile) + self.encode() + class vbr_lp(HEVC8EncoderLPTest): def before(self): super().before() @@ -173,6 +210,13 @@ def test_r2r(self, case, gop, slices, bitrate, fps, quality, refs, profile): vars(self).setdefault("r2r", 5) self.encode() + @slash.requires(have_string_api) + @slash.parametrize(*gen_hevc_vbr_lp_parameters(spec, ['main'])) + def test_strapi(self, case, gop, slices, bitrate, fps, quality, refs, profile): + self.EncoderClass = StringAPIEncoder + self.init(spec, case, gop, slices, bitrate, fps, quality, refs, profile) + self.encode() + # TCBRC is VBR LP + LDB + Strict(-1) @slash.parametrize(*gen_hevc_tcbrc_parameters(spec, ['main'])) def test_tcbrc(self, case, bitrate, fps, profile):