/src/vvenc/source/Lib/CommonLib/ProfileLevelTier.cpp
Line | Count | Source |
1 | | /* ----------------------------------------------------------------------------- |
2 | | The copyright in this software is being made available under the Clear BSD |
3 | | License, included below. No patent rights, trademark rights and/or |
4 | | other Intellectual Property Rights other than the copyrights concerning |
5 | | the Software are granted under this license. |
6 | | |
7 | | The Clear BSD License |
8 | | |
9 | | Copyright (c) 2019-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVenC Authors. |
10 | | All rights reserved. |
11 | | |
12 | | Redistribution and use in source and binary forms, with or without modification, |
13 | | are permitted (subject to the limitations in the disclaimer below) provided that |
14 | | the following conditions are met: |
15 | | |
16 | | * Redistributions of source code must retain the above copyright notice, |
17 | | this list of conditions and the following disclaimer. |
18 | | |
19 | | * Redistributions in binary form must reproduce the above copyright |
20 | | notice, this list of conditions and the following disclaimer in the |
21 | | documentation and/or other materials provided with the distribution. |
22 | | |
23 | | * Neither the name of the copyright holder nor the names of its |
24 | | contributors may be used to endorse or promote products derived from this |
25 | | software without specific prior written permission. |
26 | | |
27 | | NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY |
28 | | THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
29 | | CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
30 | | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
31 | | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
32 | | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
33 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
34 | | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
35 | | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER |
36 | | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
37 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
38 | | POSSIBILITY OF SUCH DAMAGE. |
39 | | |
40 | | |
41 | | ------------------------------------------------------------------------------------------- */ |
42 | | |
43 | | /** \file ProfileLevelTier.cpp |
44 | | \brief Handle profile, level and tier information. |
45 | | */ |
46 | | |
47 | | |
48 | | #include "ProfileLevelTier.h" |
49 | | #include "CommonLib/Slice.h" |
50 | | #include <math.h> |
51 | | |
52 | | namespace vvenc { |
53 | | |
54 | | uint32_t LevelTierFeatures::getMaxPicWidthInLumaSamples() const |
55 | 0 | { |
56 | 0 | return uint32_t(sqrt(maxLumaPs*8.0)); |
57 | 0 | } |
58 | | |
59 | | uint32_t LevelTierFeatures::getMaxPicHeightInLumaSamples() const |
60 | 0 | { |
61 | 0 | return uint32_t(sqrt(maxLumaPs*8.0)); |
62 | 0 | } |
63 | | |
64 | | static const uint64_t MAX_CNFUINT64 = std::numeric_limits<uint64_t>::max(); |
65 | | |
66 | | static const LevelTierFeatures mainLevelTierInfo[] = |
67 | | { |
68 | | // level, maxlumaps, maxcpb[tier],, maxSlicesPerAu,maxTilesPerAu,cols,rows, maxLumaSr, maxBr[tier],, minCr[tier],, |
69 | | { VVENC_LEVEL1 , 36864, { 350, 0 }, 16, 1, 1, 1, 552960ULL, { 128, 0 }, { 2, 2} }, |
70 | | { VVENC_LEVEL2 , 122880, { 1500, 0 }, 16, 1, 1, 1, 3686400ULL, { 1500, 0 }, { 2, 2} }, |
71 | | { VVENC_LEVEL2_1, 245760, { 3000, 0 }, 20, 1, 1, 1, 7372800ULL, { 3000, 0 }, { 2, 2} }, |
72 | | { VVENC_LEVEL3 , 552960, { 6000, 0 }, 30, 4, 2, 2, 16588800ULL, { 6000, 0 }, { 2, 2} }, |
73 | | { VVENC_LEVEL3_1, 983040, { 10000, 0 }, 40, 9, 3, 3, 33177600ULL, { 10000, 0 }, { 2, 2} }, |
74 | | { VVENC_LEVEL4 , 2228224, { 12000, 30000 }, 75, 25, 5, 5, 66846720ULL, { 12000, 30000 }, { 4, 4} }, |
75 | | { VVENC_LEVEL4_1, 2228224, { 20000, 50000 }, 75, 25, 5, 5, 133693440ULL, { 20000, 50000 }, { 4, 4} }, |
76 | | { VVENC_LEVEL5 , 8912896, { 25000, 100000 }, 200, 110, 10, 11, 267386880ULL, { 25000, 100000 }, { 6, 4} }, |
77 | | { VVENC_LEVEL5_1, 8912896, { 40000, 160000 }, 200, 110, 10, 11, 534773760ULL, { 40000, 160000 }, { 8, 4} }, |
78 | | { VVENC_LEVEL5_2, 8912896, { 60000, 240000 }, 200, 110, 10, 11, 1069547520ULL, { 60000, 240000 }, { 8, 4} }, |
79 | | { VVENC_LEVEL6 , 35651584, { 80000, 240000 }, 600, 440, 20, 22, 1069547520ULL, { 60000, 240000 }, { 8, 4} }, |
80 | | { VVENC_LEVEL6_1, 35651584, { 120000, 480000 }, 600, 440, 20, 22, 2139095040ULL, { 120000, 480000 }, { 8, 4} }, |
81 | | { VVENC_LEVEL6_2, 35651584, { 180000, 800000 }, 600, 440, 20, 22, 4278190080ULL, { 240000, 800000 }, { 8, 4} }, |
82 | | { VVENC_LEVEL6_3, 80216064, { 240000, 800000 }, 1000, 990, 30, 33, 4812963840ULL, { 320000, 800000 }, { 8, 4} }, |
83 | | { VVENC_LEVEL15_5, MAX_UINT,{ MAX_UINT, MAX_UINT }, MAX_UINT, MAX_UINT, MAX_UINT, MAX_UINT, MAX_CNFUINT64, {MAX_UINT, MAX_UINT }, { 0, 0} }, |
84 | | { VVENC_LEVEL_AUTO } |
85 | | }; |
86 | | |
87 | | static const ProfileFeatures validProfiles[] = { |
88 | | // profile, pNameString, maxBitDepth, maxChrFmt, lvl15.5, cpbvcl, cpbnal, fcf*1000, mincr*100, levelInfo |
89 | | // most constrained profiles must appear first. |
90 | | { VVENC_MAIN_10_STILL_PICTURE, "Main_10_Still_Picture", 10, CHROMA_420, true, 1000, 1100, 1875, 100, |
91 | | mainLevelTierInfo, true }, |
92 | | { VVENC_MULTILAYER_MAIN_10_STILL_PICTURE, "Multilayer_Main_10_Still_Picture", 10, CHROMA_420, true, 1000, 1100, |
93 | | 1875, 100, mainLevelTierInfo, true }, |
94 | | { VVENC_MAIN_10_444_STILL_PICTURE, "Main_444_10_Still_Picture", 10, CHROMA_444, true, 2500, 2750, 3750, 75, |
95 | | mainLevelTierInfo, true }, |
96 | | { VVENC_MULTILAYER_MAIN_10_444_STILL_PICTURE, "Multilayer_Main_444_10_Still_Picture", 10, CHROMA_444, true, 2500, |
97 | | 2750, 3750, 75, mainLevelTierInfo, true }, |
98 | | { VVENC_MAIN_10, "Main_10", 10, CHROMA_420, false, 1000, 1100, 1875, 100, mainLevelTierInfo, false }, |
99 | | { VVENC_MULTILAYER_MAIN_10, "Multilayer_Main_10", 10, CHROMA_420, false, 1000, 1100, 1875, 100, mainLevelTierInfo, |
100 | | false }, |
101 | | { VVENC_MAIN_10_444, "Main_444_10", 10, CHROMA_444, false, 2500, 2750, 3750, 75, mainLevelTierInfo, false }, |
102 | | { VVENC_MULTILAYER_MAIN_10_444, "Multilayer_Main_444_10", 10, CHROMA_444, false, 2500, 2750, 3750, 75, |
103 | | mainLevelTierInfo, false }, |
104 | | { VVENC_PROFILE_AUTO, 0 } |
105 | | }; |
106 | | |
107 | | const ProfileFeatures *ProfileFeatures::getProfileFeatures(const vvencProfile p) |
108 | 0 | { |
109 | 0 | int i; |
110 | 0 | for (i = 0; validProfiles[i].profile != VVENC_PROFILE_AUTO; i++) |
111 | 0 | { |
112 | 0 | if (validProfiles[i].profile == p) |
113 | 0 | { |
114 | 0 | return &validProfiles[i]; |
115 | 0 | } |
116 | 0 | } |
117 | | |
118 | 0 | return &validProfiles[i]; |
119 | 0 | } |
120 | | |
121 | | vvencLevel LevelTierFeatures::getMaxLevel(vvencProfile profile) |
122 | 0 | { |
123 | 0 | const ProfileFeatures* pf = ProfileFeatures::getProfileFeatures( profile ); |
124 | 0 | vvencLevel maxLevel = ( pf && pf->canUseLevel15p5 ) ? vvencLevel::VVENC_LEVEL15_5 : vvencLevel::VVENC_LEVEL6_3; |
125 | 0 | return maxLevel; |
126 | 0 | } |
127 | | |
128 | | vvencLevel LevelTierFeatures::getLevelForInput( uint32_t width, uint32_t height, bool tier, int temporalRate, int temporalScale, int bitrate ) |
129 | 0 | { |
130 | 0 | uint64_t samplesPerSec = ((uint64_t)temporalRate*(uint64_t)width*(uint64_t)height)/temporalScale; |
131 | 0 | uint32_t br = ( uint32_t ) bitrate / 1000; // don't assume bitrate if not set, ignore the condition since usually always satisfied |
132 | |
|
133 | 0 | for (const auto& info: mainLevelTierInfo ) |
134 | 0 | { |
135 | 0 | if ( width <= info.getMaxPicWidthInLumaSamples() && |
136 | 0 | height <= info.getMaxPicHeightInLumaSamples() && |
137 | 0 | samplesPerSec <= info.maxLumaSr && |
138 | 0 | br <= info.maxBr[tier?1:0] && |
139 | 0 | info.level != VVENC_LEVEL_AUTO ) |
140 | 0 | { |
141 | 0 | return info.level; |
142 | 0 | } |
143 | 0 | } |
144 | | |
145 | 0 | return VVENC_NUMBER_OF_LEVELS; |
146 | 0 | } |
147 | | |
148 | | void LevelTierFeatures::getMaxTileColsRowsPerLevel( vvencLevel level, uint32_t &maxCols, uint32_t &maxRows ) |
149 | 0 | { |
150 | 0 | for (const auto& info: mainLevelTierInfo ) |
151 | 0 | { |
152 | 0 | if( level == info.level ) |
153 | 0 | { |
154 | 0 | maxCols = info.maxTileCols; |
155 | 0 | maxRows = info.maxTileRows; |
156 | 0 | return; |
157 | 0 | } |
158 | 0 | } |
159 | | |
160 | 0 | maxCols = MAX_TILE_COLS; |
161 | 0 | maxRows = MAX_TILES / MAX_TILE_COLS; |
162 | 0 | } |
163 | | |
164 | | void ProfileLevelTierFeatures::extractPTLInformation(const SPS &sps) |
165 | 0 | { |
166 | 0 | const ProfileTierLevel &spsPtl = sps.profileTierLevel; |
167 | |
|
168 | 0 | m_pProfile = nullptr; |
169 | 0 | m_pLevelTier = nullptr; |
170 | 0 | m_tier = spsPtl.tierFlag; |
171 | | |
172 | | // Identify the profile from the profile Idc, and possibly other constraints. |
173 | 0 | for(int32_t i=0; validProfiles[i].profile != VVENC_PROFILE_AUTO; i++) |
174 | 0 | { |
175 | 0 | if (spsPtl.profileIdc == validProfiles[i].profile) |
176 | 0 | { |
177 | 0 | m_pProfile = &(validProfiles[i]); |
178 | 0 | break; |
179 | 0 | } |
180 | 0 | } |
181 | |
|
182 | 0 | if (m_pProfile != nullptr) |
183 | 0 | { |
184 | | // Now identify the level: |
185 | 0 | const LevelTierFeatures *pLTF = m_pProfile->pLevelTiersListInfo; |
186 | 0 | const vvencLevel spsLevelName = spsPtl.levelIdc; |
187 | 0 | if (spsLevelName!=VVENC_LEVEL15_5 || m_pProfile->canUseLevel15p5) |
188 | 0 | { |
189 | 0 | for(int i=0; pLTF[i].level!=VVENC_LEVEL_AUTO; i++) |
190 | 0 | { |
191 | 0 | if (pLTF[i].level == spsLevelName) |
192 | 0 | { |
193 | 0 | m_pLevelTier = &(pLTF[i]); |
194 | 0 | break; |
195 | 0 | } |
196 | 0 | } |
197 | 0 | } |
198 | 0 | } |
199 | 0 | } |
200 | | |
201 | | double ProfileLevelTierFeatures::getMinCr() const |
202 | 0 | { |
203 | 0 | return (m_pLevelTier!=0 && m_pProfile!=0) ? (m_pProfile->minCrScaleFactorx100 * m_pLevelTier->minCrBase[m_tier?1:0])/100.0 : 0.0 ; |
204 | 0 | } |
205 | | |
206 | | uint64_t ProfileLevelTierFeatures::getCpbSizeInBits() const |
207 | 0 | { |
208 | 0 | return (m_pLevelTier!=0 && m_pProfile!=0) ? uint64_t(m_pProfile->cpbVclFactor) * m_pLevelTier->maxCpb[m_tier?1:0] : uint64_t(0); |
209 | 0 | } |
210 | | |
211 | | uint32_t ProfileLevelTierFeatures::getMaxDpbSize( uint32_t picSizeMaxInSamplesY ) const |
212 | 0 | { |
213 | 0 | const uint32_t maxDpbPicBuf = 8; |
214 | 0 | uint32_t maxDpbSize; |
215 | |
|
216 | 0 | if (m_pLevelTier->level == VVENC_LEVEL15_5) |
217 | 0 | { |
218 | | // maxDpbSize is unconstrained in this case |
219 | 0 | maxDpbSize = std::numeric_limits<uint32_t>::max(); |
220 | 0 | } |
221 | 0 | else if (2 * picSizeMaxInSamplesY <= m_pLevelTier->maxLumaPs) |
222 | 0 | { |
223 | 0 | maxDpbSize = 2 * maxDpbPicBuf; |
224 | 0 | } |
225 | 0 | else if (3 * picSizeMaxInSamplesY <= 2 * m_pLevelTier->maxLumaPs) |
226 | 0 | { |
227 | 0 | maxDpbSize = 3 * maxDpbPicBuf / 2; |
228 | 0 | } |
229 | 0 | else |
230 | 0 | { |
231 | 0 | maxDpbSize = maxDpbPicBuf; |
232 | 0 | } |
233 | |
|
234 | 0 | return maxDpbSize; |
235 | 0 | } |
236 | | |
237 | | } //namespace |