Skip to content

Commit 03892e5

Browse files
committed
AV profile and tier selection fix.
1 parent b5d0d26 commit 03892e5

File tree

3 files changed

+84
-48
lines changed

3 files changed

+84
-48
lines changed

vk_video_encoder/libs/VkVideoEncoder/VkEncoderConfigAV1.cpp

+50-36
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@ int EncoderConfigAV1::DoParseArguments(int argc, char* argv[])
164164
return 0;
165165
}
166166

167-
bool EncoderConfigAV1::InitSequenceHeader(StdVideoAV1SequenceHeader *seqHdr)
167+
bool EncoderConfigAV1::InitSequenceHeader(StdVideoAV1SequenceHeader *seqHdr,
168+
StdVideoEncodeAV1OperatingPointInfo* opInfo)
168169
{
169170
memset(seqHdr, 0, sizeof(StdVideoAV1SequenceHeader));
170171

@@ -180,6 +181,9 @@ bool EncoderConfigAV1::InitSequenceHeader(StdVideoAV1SequenceHeader *seqHdr)
180181
seqHdr->flags.enable_cdef = enableCdef ? 1 : 0;
181182
seqHdr->flags.enable_restoration = enableLr ? 1 : 0;
182183

184+
opInfo->seq_level_idx = level;
185+
opInfo->seq_tier = tier;
186+
183187
return true;
184188
}
185189

@@ -260,49 +264,59 @@ int8_t EncoderConfigAV1::InitDpbCount()
260264
return dpbCount;
261265
}
262266

263-
bool EncoderConfigAV1::DetermineLevelTier()
267+
bool EncoderConfigAV1::ValidateLevel(uint32_t lvl, uint32_t lvlTier)
264268
{
265269
uint32_t frameRateNum = (frameRateNumerator > 0) ? frameRateNumerator : (uint32_t)FRAME_RATE_NUM_DEFAULT;
266270
uint32_t frameRateDenom = (frameRateDenominator > 0) ? frameRateDenominator : (uint32_t)FRAME_RATE_DEN_DEFAULT;
267271
uint32_t picSize = encodeWidth * encodeHeight;
268-
uint64_t displayRate = (frameRateNum * picSize) / frameRateDenom;
269-
uint64_t decodeRate = ((frameRateNum + 0) * picSize) / frameRateDenom;
272+
uint64_t displayRate = ((uint64_t)frameRateNum * picSize) / frameRateDenom;
273+
uint64_t decodeRate = (((uint64_t)frameRateNum + 0) * picSize) / frameRateDenom;
270274
uint32_t headerRate = (frameRateNum + 0) / frameRateDenom;
271275

272-
uint32_t lvl = STD_VIDEO_AV1_LEVEL_2_0;
276+
if (levelLimits[lvl].level == STD_VIDEO_AV1_LEVEL_INVALID) return false;
277+
278+
if (picSize > levelLimits[lvl].maxPicSize) return false;
279+
if (encodeWidth > levelLimits[lvl].maxHSize) return false;
280+
if (encodeHeight > levelLimits[lvl].maxVSize) return false;
281+
if (displayRate > levelLimits[lvl].maxDisplayRate) return false;
282+
if (decodeRate > levelLimits[lvl].maxDecodeRate) return false;
283+
if (headerRate > levelLimits[lvl].maxHeaderRate) return false;
284+
285+
if ((hrdBitrate != 0) || (averageBitrate != 0)) {
286+
uint32_t _maxBitrate = std::max(hrdBitrate, averageBitrate);
287+
uint32_t picSizeProfileFactor = (profile == STD_VIDEO_AV1_PROFILE_MAIN) ? 15 : ((profile == STD_VIDEO_AV1_PROFILE_HIGH ? 30 : 26));
288+
// Estimate max compressed size to be up to 16 frames at average rate
289+
uint32_t maxCompressedSize = std::max(1u, ((_maxBitrate << 4) / frameRateNum) * frameRateDenom);
290+
double minCR = ((double)picSize * picSizeProfileFactor) / maxCompressedSize;
291+
292+
if (minCR < GetLevelMinCR(lvl, lvlTier, (double)decodeRate)) return false;
293+
// Add a safety margin of 1.5x
294+
if (((3 * _maxBitrate) >> 1) > GetLevelMaxBitrate(lvl, lvlTier)) return false;
295+
}
296+
297+
return true;
298+
}
273299

274-
// TODO: how to choose tier
275-
tier = 0;
300+
bool EncoderConfigAV1::DetermineLevelTier()
301+
{
302+
uint32_t lvl = STD_VIDEO_AV1_LEVEL_2_0;
276303

277304
for (; lvl <= STD_VIDEO_AV1_LEVEL_7_3; lvl++) {
278-
if (levelLimits[lvl].level == STD_VIDEO_AV1_LEVEL_INVALID) continue;
279-
280-
level = (StdVideoAV1Level)lvl;
281-
282-
if (picSize > levelLimits[lvl].maxPicSize) continue;
283-
if (encodeWidth > levelLimits[lvl].maxHSize) continue;
284-
if (encodeHeight > levelLimits[lvl].maxVSize) continue;
285-
if (displayRate > levelLimits[lvl].maxDisplayRate) continue;
286-
if (decodeRate > levelLimits[lvl].maxDecodeRate) continue;
287-
if (headerRate > levelLimits[lvl].maxHeaderRate) continue;
288-
289-
// TODO: if ratecontrol params are specified at the command line use the below code
290-
// otherwise, use level max values.
291-
//if (hrdBitrate != 0) {
292-
// if (lvl > STD_VIDEO_AV1_LEVEL_4_0) {
293-
// tier = 1;
294-
// }
295-
// uint32_t lvlBitrate = GetLevelBitrate();
296-
// if (hrdBitrate > lvlBitrate) continue;
297-
//}
298-
299-
// double minCompressRatio = GetMinCompressRatio(decodeRate);
300-
// uint32_t compressedSize = 0; // TODO: How to estimate?
301-
// uint32_t uncompressedSize = GetUncompressedSize();
302-
// uint32_t compressedRatio = uncompressedSize / compressedSize;
303-
// if (compressedRatio < minCompressRatio) continue;
304-
305-
break;
305+
if (ValidateLevel(lvl, 0)) { // validate with tier 0
306+
level = (StdVideoAV1Level)lvl;
307+
tier = 0;
308+
break;
309+
}
310+
311+
if ((lvl >= STD_VIDEO_AV1_LEVEL_4_0) && ValidateLevel(lvl, 1)) { // validate with tier 1
312+
level = (StdVideoAV1Level)lvl;
313+
tier = 1;
314+
break;
315+
}
316+
}
317+
if (lvl > STD_VIDEO_AV1_LEVEL_7_3) {
318+
level = STD_VIDEO_AV1_LEVEL_7_3;
319+
tier = 0;
306320
}
307321

308322
return true;
@@ -313,7 +327,7 @@ bool EncoderConfigAV1::InitRateControl()
313327
DetermineLevelTier();
314328

315329
// use level max values for now. Limit it to 120Mbits/sec
316-
uint32_t levelBitrate = std::min(GetLevelBitrate(), 120000000u);
330+
uint32_t levelBitrate = std::min(GetLevelBitrate(level, tier), 120000000u);
317331

318332
// If no bitrate is specified, use the level limit
319333
if (averageBitrate == 0) {

vk_video_encoder/libs/VkVideoEncoder/VkEncoderConfigAV1.h

+32-10
Original file line numberDiff line numberDiff line change
@@ -124,29 +124,53 @@ struct EncoderConfigAV1 : public EncoderConfig {
124124
VkVideoEncodeAV1RateControlInfoKHR* rcInfoAV1,
125125
VkVideoEncodeAV1RateControlLayerInfoKHR* rcLayerInfoAV1);
126126

127-
bool InitSequenceHeader(StdVideoAV1SequenceHeader* seqHeader);
127+
bool InitSequenceHeader(StdVideoAV1SequenceHeader* seqHeader,
128+
StdVideoEncodeAV1OperatingPointInfo* opInfo);
128129

129130
virtual EncoderConfigAV1* GetEncoderConfigAV1() override {
130131
return this;
131132
}
132133

134+
bool ValidateLevel(uint32_t lLevel, uint32_t lTier);
133135

134136
bool DetermineLevelTier();
135137

136-
uint32_t GetLevelMaxBitrate() {
137-
return (tier == 0) ? levelLimits[level].mainBps : levelLimits[level].highBps;
138+
uint32_t GetLevelMaxBitrate(uint32_t lLevel, uint32_t lTier) {
139+
if (lLevel < STD_VIDEO_AV1_LEVEL_4_0) {
140+
lTier = 0;
141+
}
142+
143+
uint32_t _maxBitrate = lTier ? levelLimits[lLevel].highBps : levelLimits[lLevel].mainBps;
144+
uint32_t bitrateProfileFactor = (profile == STD_VIDEO_AV1_PROFILE_MAIN) ? 1 :
145+
((profile == STD_VIDEO_AV1_PROFILE_HIGH) ? 1 : 3);
146+
147+
return _maxBitrate * bitrateProfileFactor;
138148
}
139149

140-
uint32_t GetLevelBitrate() {
150+
double GetLevelMinCR(uint32_t lLevel, uint32_t lTier, double decodeRate) {
151+
if (lLevel < STD_VIDEO_AV1_LEVEL_4_0) {
152+
lTier = 0;
153+
}
154+
155+
uint32_t minCRBase = lTier ? levelLimits[lLevel].highCR : levelLimits[lLevel].mainCR;
156+
double speedAdj = decodeRate / levelLimits[lLevel].maxDisplayRate;
157+
158+
return std::max(minCRBase * speedAdj, 0.8);
159+
}
160+
161+
uint32_t GetLevelBitrate(uint32_t lLevel, uint32_t lTier) {
162+
if (lLevel < STD_VIDEO_AV1_LEVEL_4_0) {
163+
lTier = 0;
164+
}
141165
uint32_t bitrateProfileFactor = (profile == STD_VIDEO_AV1_PROFILE_MAIN) ? 1 :
142166
((profile == STD_VIDEO_AV1_PROFILE_HIGH) ? 2 : 3);
143-
uint32_t _maxBitrate = (tier == 0) ? levelLimits[level].mainBps : levelLimits[level].highBps;
167+
uint32_t _maxBitrate = (lTier == 0) ? levelLimits[lLevel].mainBps : levelLimits[lLevel].highBps;
144168
return _maxBitrate * bitrateProfileFactor;
145169
}
146170

147-
double GetMinCompressRatio(uint32_t decodeRate) {
148-
double speedAdj = (double)decodeRate / (double)levelLimits[level].maxDisplayRate;
149-
double minCompBasis = (tier == 0) ? levelLimits[level].mainCR : levelLimits[level].highCR;
171+
double GetMinCompressRatio(uint32_t lLevel, uint32_t lTier, uint32_t decodeRate) {
172+
double speedAdj = (double)decodeRate / (double)levelLimits[lLevel].maxDisplayRate;
173+
double minCompBasis = (lTier == 0) ? levelLimits[lLevel].mainCR : levelLimits[lLevel].highCR;
150174
return std::max(0.8, minCompBasis * speedAdj);
151175
}
152176

@@ -162,8 +186,6 @@ struct EncoderConfigAV1 : public EncoderConfig {
162186
VkVideoEncodeAV1CapabilitiesKHR av1EncodeCapabilities{ VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_CAPABILITIES_KHR };
163187
VkVideoEncodeAV1QualityLevelPropertiesKHR av1QualityLevelProperties{ VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_QUALITY_LEVEL_PROPERTIES_KHR };
164188
VkVideoEncodeAV1QuantizationMapCapabilitiesKHR av1QuantizationMapCapabilities { VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_QUANTIZATION_MAP_CAPABILITIES_KHR };
165-
uint32_t maxBitrate{};
166-
uint32_t hrdBitrate{};
167189
uint32_t vbvBufferSize{};
168190
uint32_t vbvInitialDelay{};
169191
uint32_t pic_width_in_sbs{};

vk_video_encoder/libs/VkVideoEncoder/VkVideoEncoderAV1.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,11 @@ VkResult VkVideoEncoderAV1::InitEncoderCodec(VkSharedBaseObj<EncoderConfig>& enc
105105

106106
m_encoderConfig->GetRateControlParameters(&m_rateControlInfo, m_rateControlLayersInfo, &m_stateAV1.m_rateControlInfoAV1, m_stateAV1.m_rateControlLayersInfoAV1);
107107

108-
m_encoderConfig->InitSequenceHeader(&m_stateAV1.m_sequenceHeader);
108+
m_encoderConfig->InitSequenceHeader(&m_stateAV1.m_sequenceHeader, m_stateAV1.m_operatingPointsInfo);
109109

110110
VideoSessionParametersInfoAV1 videoSessionParametersInfo(*m_videoSession, &m_stateAV1.m_sequenceHeader,
111111
nullptr/*decoderModelInfo*/,
112-
1, nullptr /*operatingPointsInfo*/,
112+
1, m_stateAV1.m_operatingPointsInfo /*operatingPointsInfo*/,
113113
encoderConfig->enableQpMap, m_qpMapTexelSize);
114114
VkVideoSessionParametersCreateInfoKHR* encodeSessionParametersCreateInfo = videoSessionParametersInfo.getVideoSessionParametersInfo();
115115
VkVideoSessionParametersKHR sessionParameters;

0 commit comments

Comments
 (0)