xref: /aosp_15_r20/frameworks/av/media/libmedia/VideoCapabilities.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright 2024, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "VideoCapabilities"
19 
20 #include <android-base/strings.h>
21 
22 #include <media/CodecCapabilities.h>
23 #include <media/VideoCapabilities.h>
24 #include <media/stagefright/foundation/ADebug.h>
25 #include <media/stagefright/MediaCodecConstants.h>
26 
27 #include <utils/Errors.h>
28 
29 namespace android {
30 
31 static const Range<int64_t> POSITIVE_INT64 = Range((int64_t)1, INT64_MAX);
32 static const Range<int32_t> BITRATE_RANGE = Range<int32_t>(0, 500000000);
33 static const Range<int32_t> FRAME_RATE_RANGE = Range<int32_t>(0, 960);
34 static const Range<Rational> POSITIVE_RATIONALS =
35             Range<Rational>(Rational((int32_t)1, INT32_MAX), Rational(INT32_MAX, (int32_t)1));
36 
getBitrateRange() const37 const Range<int32_t>& VideoCapabilities::getBitrateRange() const {
38     return mBitrateRange;
39 }
40 
getSupportedWidths() const41 const Range<int32_t>& VideoCapabilities::getSupportedWidths() const {
42     return mWidthRange;
43 }
44 
getSupportedHeights() const45 const Range<int32_t>& VideoCapabilities::getSupportedHeights() const {
46     return mHeightRange;
47 }
48 
getWidthAlignment() const49 int32_t VideoCapabilities::getWidthAlignment() const {
50     return mWidthAlignment;
51 }
52 
getHeightAlignment() const53 int32_t VideoCapabilities::getHeightAlignment() const {
54     return mHeightAlignment;
55 }
56 
getSmallerDimensionUpperLimit() const57 int32_t VideoCapabilities::getSmallerDimensionUpperLimit() const {
58     return mSmallerDimensionUpperLimit;
59 }
60 
getSupportedFrameRates() const61 const Range<int32_t>& VideoCapabilities::getSupportedFrameRates() const {
62     return mFrameRateRange;
63 }
64 
getSupportedWidthsFor(int32_t height) const65 std::optional<Range<int32_t>> VideoCapabilities::getSupportedWidthsFor(int32_t height) const {
66     Range<int32_t> range = mWidthRange;
67     if (!mHeightRange.contains(height)
68             || (height % mHeightAlignment) != 0) {
69         ALOGE("unsupported height");
70         return std::nullopt;
71     }
72     const int32_t heightInBlocks = divUp(height, mBlockHeight);
73 
74     // constrain by block count and by block aspect ratio
75     const int32_t minWidthInBlocks = std::max(
76             divUp(mBlockCountRange.lower(), heightInBlocks),
77             (int32_t)std::ceil(mBlockAspectRatioRange.lower().asDouble()
78                     * heightInBlocks));
79     const int32_t maxWidthInBlocks = std::min(
80             mBlockCountRange.upper() / heightInBlocks,
81             (int32_t)(mBlockAspectRatioRange.upper().asDouble()
82                     * heightInBlocks));
83     range = range.intersect(
84             (minWidthInBlocks - 1) * mBlockWidth + mWidthAlignment,
85             maxWidthInBlocks * mBlockWidth);
86 
87     // constrain by smaller dimension limit
88     if (height > mSmallerDimensionUpperLimit) {
89         range = range.intersect(1, mSmallerDimensionUpperLimit);
90     }
91 
92     // constrain by aspect ratio
93     range = range.intersect(
94             (int32_t)std::ceil(mAspectRatioRange.lower().asDouble()
95                     * height),
96             (int32_t)(mAspectRatioRange.upper().asDouble() * height));
97     return range;
98 }
99 
getSupportedHeightsFor(int32_t width) const100 std::optional<Range<int32_t>> VideoCapabilities::getSupportedHeightsFor(int32_t width) const {
101     Range<int32_t> range = mHeightRange;
102     if (!mWidthRange.contains(width)
103             || (width % mWidthAlignment) != 0) {
104         ALOGE("unsupported width");
105         return std::nullopt;
106     }
107     const int32_t widthInBlocks = divUp(width, mBlockWidth);
108 
109     // constrain by block count and by block aspect ratio
110     const int32_t minHeightInBlocks = std::max(
111             divUp(mBlockCountRange.lower(), widthInBlocks),
112             (int32_t)std::ceil(widthInBlocks /
113                     mBlockAspectRatioRange.upper().asDouble()));
114     const int32_t maxHeightInBlocks = std::min(
115             mBlockCountRange.upper() / widthInBlocks,
116             (int32_t)(widthInBlocks /
117                     mBlockAspectRatioRange.lower().asDouble()));
118     range = range.intersect(
119             (minHeightInBlocks - 1) * mBlockHeight + mHeightAlignment,
120             maxHeightInBlocks * mBlockHeight);
121 
122     // constrain by smaller dimension limit
123     if (width > mSmallerDimensionUpperLimit) {
124         range = range.intersect(1, mSmallerDimensionUpperLimit);
125     }
126 
127     // constrain by aspect ratio
128     range = range.intersect(
129             (int32_t)std::ceil(width /
130                     mAspectRatioRange.upper().asDouble()),
131             (int32_t)(width / mAspectRatioRange.lower().asDouble()));
132     return range;
133 }
134 
getSupportedFrameRatesFor(int32_t width,int32_t height) const135 std::optional<Range<double>> VideoCapabilities::getSupportedFrameRatesFor(
136         int32_t width, int32_t height) const {
137     if (!supports(std::make_optional<int32_t>(width), std::make_optional<int32_t>(height),
138             std::nullopt /* rate */)) {
139         ALOGE("Unsupported size. width: %d, height: %d", width, height);
140         return std::nullopt;
141     }
142 
143     const int32_t blockCount =
144             divUp(width, mBlockWidth) * divUp(height, mBlockHeight);
145 
146     return std::make_optional(Range(
147             std::max(mBlocksPerSecondRange.lower() / (double) blockCount,
148                 (double) mFrameRateRange.lower()),
149             std::min(mBlocksPerSecondRange.upper() / (double) blockCount,
150                 (double) mFrameRateRange.upper())));
151 }
152 
getBlockCount(int32_t width,int32_t height) const153 int32_t VideoCapabilities::getBlockCount(int32_t width, int32_t height) const {
154     return divUp(width, mBlockWidth) * divUp(height, mBlockHeight);
155 }
156 
findClosestSize(int32_t width,int32_t height) const157 std::optional<VideoSize> VideoCapabilities::findClosestSize(
158         int32_t width, int32_t height) const {
159     int32_t targetBlockCount = getBlockCount(width, height);
160     std::optional<VideoSize> closestSize;
161     int32_t minDiff = INT32_MAX;
162     for (const auto &[size, range] : mMeasuredFrameRates) {
163         int32_t diff = std::abs(targetBlockCount -
164                 getBlockCount(size.getWidth(), size.getHeight()));
165         if (diff < minDiff) {
166             minDiff = diff;
167             closestSize = size;
168         }
169     }
170     return closestSize;
171 }
172 
estimateFrameRatesFor(int32_t width,int32_t height) const173 std::optional<Range<double>> VideoCapabilities::estimateFrameRatesFor(
174         int32_t width, int32_t height) const {
175     std::optional<VideoSize> size = findClosestSize(width, height);
176     if (!size) {
177         return std::nullopt;
178     }
179     auto rangeItr = mMeasuredFrameRates.find(size.value());
180     if (rangeItr == mMeasuredFrameRates.end()) {
181         return std::nullopt;
182     }
183     Range<int64_t> range = rangeItr->second;
184     double ratio = getBlockCount(size.value().getWidth(), size.value().getHeight())
185             / (double)std::max(getBlockCount(width, height), 1);
186     return std::make_optional(Range(range.lower() * ratio, range.upper() * ratio));
187 }
188 
getAchievableFrameRatesFor(int32_t width,int32_t height) const189 std::optional<Range<double>> VideoCapabilities::getAchievableFrameRatesFor(
190         int32_t width, int32_t height) const {
191     if (!supports(std::make_optional<int32_t>(width), std::make_optional<int32_t>(height),
192             std::nullopt /* rate */)) {
193         ALOGE("Unsupported size. width: %d, height: %d", width, height);
194         return std::nullopt;
195     }
196 
197     if (mMeasuredFrameRates.empty()) {
198         ALOGW("Codec did not publish any measurement data.");
199         return std::nullopt;
200     }
201 
202     return estimateFrameRatesFor(width, height);
203 }
204 
205 // VideoCapabilities::PerformancePoint
206 
getMaxMacroBlocks() const207 int32_t VideoCapabilities::PerformancePoint::getMaxMacroBlocks() const {
208     return saturateInt64ToInt32(mWidth * (int64_t)mHeight);
209 }
210 
getWidth() const211 int32_t VideoCapabilities::PerformancePoint::getWidth() const {
212     return mWidth;
213 }
214 
getHeight() const215 int32_t VideoCapabilities::PerformancePoint::getHeight() const {
216     return mHeight;
217 }
218 
getMaxFrameRate() const219 int32_t VideoCapabilities::PerformancePoint::getMaxFrameRate() const {
220     return mMaxFrameRate;
221 }
222 
getMaxMacroBlockRate() const223 int64_t VideoCapabilities::PerformancePoint::getMaxMacroBlockRate() const {
224     return mMaxMacroBlockRate;
225 }
226 
getBlockSize() const227 VideoSize VideoCapabilities::PerformancePoint::getBlockSize() const {
228     return mBlockSize;
229 }
230 
toString() const231 std::string VideoCapabilities::PerformancePoint::toString() const {
232     int64_t blockWidth = 16 * (int64_t)mBlockSize.getWidth();
233     int64_t blockHeight = 16 * (int64_t)mBlockSize.getHeight();
234     int32_t origRate = (int32_t)divUp(mMaxMacroBlockRate, (int64_t)getMaxMacroBlocks());
235     std::string info = std::to_string(mWidth * (int64_t)16) + "x"
236             + std::to_string(mHeight * (int64_t)16) + "@" + std::to_string(origRate);
237     if (origRate < mMaxFrameRate) {
238         info += ", max " + std::to_string(mMaxFrameRate) + "fps";
239     }
240     if (blockWidth > 16 || blockHeight > 16) {
241         info += ", " + std::to_string(blockWidth) + "x"
242                 + std::to_string(blockHeight) + " blocks";
243     }
244     return "PerformancePoint(" + info + ")";
245 }
246 
init(int32_t width,int32_t height,int32_t frameRate,int32_t maxFrameRate,VideoSize blockSize)247 void VideoCapabilities::PerformancePoint::init(int32_t width, int32_t height,
248         int32_t frameRate, int32_t maxFrameRate, VideoSize blockSize) {
249     mBlockSize = VideoSize(divUp(blockSize.getWidth(), (int32_t)16),
250                             divUp(blockSize.getHeight(), (int32_t)16));
251     // Use  IsPowerOfTwoStrict as we do not want width and height to be 0;
252     if (!IsPowerOfTwoStrict(blockSize.getWidth()) || !IsPowerOfTwoStrict(blockSize.getHeight())) {
253         ALOGE("The width and height of a PerformancePoint must be the power of two and not zero."
254                 " width: %d, height: %d", blockSize.getWidth(), blockSize.getHeight());
255     }
256 
257     // these are guaranteed not to overflow as we decimate by 16
258     mWidth = (int32_t)(divUp(std::max(width, 1),
259                             std::max(blockSize.getWidth(), 16))
260                         * mBlockSize.getWidth());
261     mHeight = (int32_t)(divUp(std::max(height, 1),
262                             std::max(blockSize.getHeight(), 16))
263                         * mBlockSize.getHeight());
264     mMaxFrameRate = std::max(std::max(frameRate, maxFrameRate), 1);
265     mMaxMacroBlockRate = std::max(frameRate, 1) * (int64_t)getMaxMacroBlocks();
266 }
267 
PerformancePoint(int32_t width,int32_t height,int32_t frameRate,int32_t maxFrameRate,VideoSize blockSize)268 VideoCapabilities::PerformancePoint::PerformancePoint(int32_t width, int32_t height,
269         int32_t frameRate, int32_t maxFrameRate, VideoSize blockSize) {
270     init(width, height, frameRate, maxFrameRate, blockSize);
271 }
272 
PerformancePoint(VideoSize blockSize,int32_t width,int32_t height,int32_t maxFrameRate,int64_t maxMacroBlockRate)273 VideoCapabilities::PerformancePoint::PerformancePoint(VideoSize blockSize, int32_t width,
274         int32_t height, int32_t maxFrameRate, int64_t maxMacroBlockRate) :
275         mBlockSize(blockSize), mWidth(width), mHeight(height), mMaxFrameRate(maxFrameRate),
276         mMaxMacroBlockRate(maxMacroBlockRate) {}
277 
PerformancePoint(const PerformancePoint & pp,VideoSize newBlockSize)278 VideoCapabilities::PerformancePoint::PerformancePoint(
279         const PerformancePoint &pp, VideoSize newBlockSize) {
280     init(16 * pp.mWidth, 16 * pp.mHeight,
281             // guaranteed not to overflow as these were multiplied at construction
282             (int32_t)divUp(pp.mMaxMacroBlockRate, (int64_t)pp.getMaxMacroBlocks()),
283             pp.mMaxFrameRate,
284             VideoSize(std::max(newBlockSize.getWidth(), 16 * pp.mBlockSize.getWidth()),
285                  std::max(newBlockSize.getHeight(), 16 * pp.mBlockSize.getHeight())));
286 }
287 
PerformancePoint(int32_t width,int32_t height,int32_t frameRate)288 VideoCapabilities::PerformancePoint::PerformancePoint(
289         int32_t width, int32_t height, int32_t frameRate) {
290     init(width, height, frameRate, frameRate /* maxFrameRate */, VideoSize(16, 16));
291 }
292 
saturateInt64ToInt32(int64_t value) const293 int32_t VideoCapabilities::PerformancePoint::saturateInt64ToInt32(int64_t value) const {
294     if (value < INT32_MIN) {
295         return INT32_MIN;
296     } else if (value > INT32_MAX) {
297         return INT32_MAX;
298     } else {
299         return (int32_t)value;
300     }
301 }
302 
303 /* This method may overflow */
align(int32_t value,int32_t alignment) const304 int32_t VideoCapabilities::PerformancePoint::align(
305         int32_t value, int32_t alignment) const {
306     return divUp(value, alignment) * alignment;
307 }
308 
covers(const sp<AMessage> & format) const309 bool VideoCapabilities::PerformancePoint::covers(
310         const sp<AMessage> &format) const {
311     int32_t width, height;
312     format->findInt32(KEY_WIDTH, &width);
313     format->findInt32(KEY_HEIGHT, &height);
314     double frameRate;
315     format->findDouble(KEY_FRAME_RATE, &frameRate);
316     PerformancePoint other = PerformancePoint(
317             width, height,
318             // safely convert ceil(double) to int through float cast and std::round
319             std::round((float)(std::ceil(frameRate)))
320     );
321     return covers(other);
322 }
323 
covers(const PerformancePoint & other) const324 bool VideoCapabilities::PerformancePoint::covers(
325         const PerformancePoint &other) const {
326     // convert performance points to common block size
327     VideoSize commonSize = getCommonBlockSize(other);
328     PerformancePoint aligned = PerformancePoint(*this, commonSize);
329     PerformancePoint otherAligned = PerformancePoint(other, commonSize);
330 
331     return (aligned.getMaxMacroBlocks() >= otherAligned.getMaxMacroBlocks()
332             && aligned.mMaxFrameRate >= otherAligned.mMaxFrameRate
333             && aligned.mMaxMacroBlockRate >= otherAligned.mMaxMacroBlockRate);
334 }
335 
getCommonBlockSize(const PerformancePoint & other) const336 VideoSize VideoCapabilities::PerformancePoint::getCommonBlockSize(
337         const PerformancePoint &other) const {
338     return VideoSize(
339             16 * std::max(mBlockSize.getWidth(), other.mBlockSize.getWidth()),
340             16 * std::max(mBlockSize.getHeight(), other.mBlockSize.getHeight()));
341 }
342 
equals(const PerformancePoint & other) const343 bool VideoCapabilities::PerformancePoint::equals(
344         const PerformancePoint &other) const {
345     // convert performance points to common block size
346     VideoSize commonSize = getCommonBlockSize(other);
347     PerformancePoint aligned = PerformancePoint(*this, commonSize);
348     PerformancePoint otherAligned = PerformancePoint(other, commonSize);
349 
350     return (aligned.getMaxMacroBlocks() == otherAligned.getMaxMacroBlocks()
351             && aligned.mMaxFrameRate == otherAligned.mMaxFrameRate
352             && aligned.mMaxMacroBlockRate == otherAligned.mMaxMacroBlockRate);
353 }
354 
355 // VideoCapabilities
356 
357 const std::vector<VideoCapabilities::PerformancePoint>&
getSupportedPerformancePoints() const358         VideoCapabilities::getSupportedPerformancePoints() const {
359     return mPerformancePoints;
360 }
361 
areSizeAndRateSupported(int32_t width,int32_t height,double frameRate) const362 bool VideoCapabilities::areSizeAndRateSupported(
363         int32_t width, int32_t height, double frameRate) const {
364     return supports(std::make_optional<int32_t>(width), std::make_optional<int32_t>(height),
365             std::make_optional<double>(frameRate));
366 }
367 
isSizeSupported(int32_t width,int32_t height) const368 bool VideoCapabilities::isSizeSupported(int32_t width, int32_t height) const {
369     return supports(std::make_optional<int32_t>(width), std::make_optional<int32_t>(height),
370             std::nullopt /* rate */);
371 }
372 
supports(std::optional<int32_t> width,std::optional<int32_t> height,std::optional<double> rate) const373 bool VideoCapabilities::supports(std::optional<int32_t> width, std::optional<int32_t> height,
374         std::optional<double> rate) const {
375     bool ok = true;
376 
377     if (width) {
378         ok &= mWidthRange.contains(width.value())
379                 && (width.value() % mWidthAlignment == 0);
380     }
381     if (height) {
382         ok &= mHeightRange.contains(height.value())
383                 && (height.value() % mHeightAlignment == 0);
384     }
385     if (rate) {
386         ok &= mFrameRateRange.contains(Range<int32_t>::RangeFor(rate.value()));
387     }
388     if (height && width) {
389         ok &= std::min(height.value(), width.value()) <= mSmallerDimensionUpperLimit;
390 
391         const int32_t widthInBlocks = divUp(width.value(), mBlockWidth);
392         const int32_t heightInBlocks = divUp(height.value(), mBlockHeight);
393         const int32_t blockCount = widthInBlocks * heightInBlocks;
394         ok &= mBlockCountRange.contains(blockCount)
395                 && mBlockAspectRatioRange.contains(
396                         Rational(widthInBlocks, heightInBlocks))
397                 && mAspectRatioRange.contains(Rational(width.value(), height.value()));
398         if (rate) {
399             double blocksPerSec = blockCount * rate.value();
400             ok &= mBlocksPerSecondRange.contains(
401                     Range<int64_t>::RangeFor(blocksPerSec));
402         }
403     }
404     return ok;
405 }
406 
supportsFormat(const sp<AMessage> & format) const407 bool VideoCapabilities::supportsFormat(const sp<AMessage> &format) const {
408     int32_t widthVal, heightVal;
409     std::optional<int32_t> width = format->findInt32(KEY_WIDTH, &widthVal)
410             ? std::make_optional<int32_t>(widthVal) : std::nullopt;
411     std::optional<int32_t> height = format->findInt32(KEY_HEIGHT, &heightVal)
412             ? std::make_optional<int32_t>(heightVal) : std::nullopt;
413     double rateVal;
414     std::optional<double> rate = format->findDouble(KEY_FRAME_RATE, &rateVal)
415             ? std::make_optional<double>(rateVal) : std::nullopt;
416 
417     if (!supports(width, height, rate)) {
418         return false;
419     }
420 
421     if (!CodecCapabilities::SupportsBitrate(mBitrateRange, format)) {
422         return false;
423     }
424 
425     // we ignore color-format for now as it is not reliably reported by codec
426     return true;
427 }
428 
429 // static
Create(std::string mediaType,std::vector<ProfileLevel> profLevs,const sp<AMessage> & format)430 std::shared_ptr<VideoCapabilities> VideoCapabilities::Create(std::string mediaType,
431         std::vector<ProfileLevel> profLevs, const sp<AMessage> &format) {
432     std::shared_ptr<VideoCapabilities> caps(new VideoCapabilities());
433     caps->init(mediaType, profLevs, format);
434     return caps;
435 }
436 
init(std::string mediaType,std::vector<ProfileLevel> profLevs,const sp<AMessage> & format)437 void VideoCapabilities::init(std::string mediaType, std::vector<ProfileLevel> profLevs,
438         const sp<AMessage> &format) {
439     mMediaType = mediaType;
440     mProfileLevels = profLevs;
441     mError = 0;
442 
443     initWithPlatformLimits();
444     applyLevelLimits();
445     parseFromInfo(format);
446     updateLimits();
447 }
448 
getBlockSize() const449 VideoSize VideoCapabilities::getBlockSize() const {
450     return VideoSize(mBlockWidth, mBlockHeight);
451 }
452 
getBlockCountRange() const453 const Range<int32_t>& VideoCapabilities::getBlockCountRange() const {
454     return mBlockCountRange;
455 }
456 
getBlocksPerSecondRange() const457 const Range<int64_t>& VideoCapabilities::getBlocksPerSecondRange() const {
458     return mBlocksPerSecondRange;
459 }
460 
getAspectRatioRange(bool blocks) const461 Range<Rational> VideoCapabilities::getAspectRatioRange(bool blocks) const {
462     return blocks ? mBlockAspectRatioRange : mAspectRatioRange;
463 }
464 
initWithPlatformLimits()465 void VideoCapabilities::initWithPlatformLimits() {
466     mBitrateRange = BITRATE_RANGE;
467 
468     mWidthRange  = VideoSize::GetAllowedDimensionRange();
469     mHeightRange = VideoSize::GetAllowedDimensionRange();
470     mFrameRateRange = FRAME_RATE_RANGE;
471 
472     mHorizontalBlockRange = VideoSize::GetAllowedDimensionRange();
473     mVerticalBlockRange   = VideoSize::GetAllowedDimensionRange();
474 
475     // full positive ranges are supported as these get calculated
476     mBlockCountRange      = POSITIVE_INT32;
477     mBlocksPerSecondRange = POSITIVE_INT64;
478 
479     mBlockAspectRatioRange = POSITIVE_RATIONALS;
480     mAspectRatioRange      = POSITIVE_RATIONALS;
481 
482     // YUV 4:2:0 requires 2:2 alignment
483     mWidthAlignment = 2;
484     mHeightAlignment = 2;
485     mBlockWidth = 2;
486     mBlockHeight = 2;
487     mSmallerDimensionUpperLimit = VideoSize::GetAllowedDimensionRange().upper();
488 }
489 
490 std::vector<VideoCapabilities::PerformancePoint>
getPerformancePoints(const sp<AMessage> & format) const491         VideoCapabilities::getPerformancePoints(
492         const sp<AMessage> &format) const {
493     std::vector<PerformancePoint> ret;
494     AMessage::Type type;
495     for (int i = 0; i < format->countEntries(); i++) {
496         const char *name = format->getEntryNameAt(i, &type);
497         AString rangeStr;
498         if (!format->findString(name, &rangeStr)) {
499             continue;
500         }
501 
502         const std::string key = std::string(name);
503         // looking for: performance-point-WIDTHxHEIGHT-range
504 
505         // check none performance point
506         if (key == "performance-point-none" && ret.size() == 0) {
507             // This means that component knowingly did not publish performance points.
508             // This is different from when the component forgot to publish performance
509             // points.
510             return ret;
511         }
512 
513         // parse size from key
514         std::regex sizeRegex("performance-point-(.+)-range");
515         std::smatch sizeMatch;
516         if (!std::regex_match(key, sizeMatch, sizeRegex)) {
517             continue;
518         }
519         std::optional<VideoSize> size = VideoSize::ParseSize(sizeMatch[1].str());
520         if (!size || size.value().getWidth() * size.value().getHeight() <= 0) {
521             continue;
522         }
523 
524         // parse range from value
525         std::optional<Range<int64_t>> range = Range<int64_t>::Parse(std::string(rangeStr.c_str()));
526         if (!range || range.value().lower() < 0 || range.value().upper() < 0) {
527             continue;
528         }
529 
530         PerformancePoint given = PerformancePoint(
531                 size.value().getWidth(), size.value().getHeight(), (int32_t)range.value().lower(),
532                 (int32_t)range.value().upper(), VideoSize(mBlockWidth, mBlockHeight));
533         PerformancePoint rotated = PerformancePoint(
534                 size.value().getHeight(), size.value().getWidth(), (int32_t)range.value().lower(),
535                 (int32_t)range.value().upper(), VideoSize(mBlockWidth, mBlockHeight));
536         ret.push_back(given);
537         if (!given.covers(rotated)) {
538             ret.push_back(rotated);
539         }
540     }
541 
542     // check if the component specified no performance point indication
543     if (ret.size() == 0) {
544         return ret;
545     }
546 
547     // sort reversed by area first, then by frame rate
548     std::sort(ret.begin(), ret.end(), [](const PerformancePoint &a, const PerformancePoint &b) {
549         return -((a.getMaxMacroBlocks() != b.getMaxMacroBlocks()) ?
550                         (a.getMaxMacroBlocks() < b.getMaxMacroBlocks() ? -1 : 1) :
551                 (a.getMaxMacroBlockRate() != b.getMaxMacroBlockRate()) ?
552                         (a.getMaxMacroBlockRate() < b.getMaxMacroBlockRate() ? -1 : 1) :
553                 (a.getMaxFrameRate() != b.getMaxFrameRate()) ?
554                         (a.getMaxFrameRate() < b.getMaxFrameRate() ? -1 : 1) : 0);
555     });
556 
557     return ret;
558 }
559 
560 std::map<VideoSize, Range<int64_t>, VideoSizeCompare> VideoCapabilities
getMeasuredFrameRates(const sp<AMessage> & format) const561         ::getMeasuredFrameRates(const sp<AMessage> &format) const {
562     std::map<VideoSize, Range<int64_t>, VideoSizeCompare> ret;
563     AMessage::Type type;
564     for (int i = 0; i < format->countEntries(); i++) {
565         const char *name = format->getEntryNameAt(i, &type);
566         AString rangeStr;
567         if (!format->findString(name, &rangeStr)) {
568             continue;
569         }
570 
571         const std::string key = std::string(name);
572         // looking for: measured-frame-rate-WIDTHxHEIGHT-range
573 
574         std::regex sizeRegex("measured-frame-rate-(.+)-range");
575         std::smatch sizeMatch;
576         if (!std::regex_match(key, sizeMatch, sizeRegex)) {
577             continue;
578         }
579 
580         std::optional<VideoSize> size = VideoSize::ParseSize(sizeMatch[1].str());
581         if (!size || size.value().getWidth() * size.value().getHeight() <= 0) {
582             continue;
583         }
584 
585         std::optional<Range<int64_t>> range = Range<int64_t>::Parse(std::string(rangeStr.c_str()));
586         if (!range || range.value().lower() < 0 || range.value().upper() < 0) {
587             continue;
588         }
589 
590         ret.emplace(size.value(), range.value());
591     }
592     return ret;
593 }
594 
595 // static
596 std::optional<std::pair<Range<int32_t>, Range<int32_t>>> VideoCapabilities
ParseWidthHeightRanges(const std::string & str)597         ::ParseWidthHeightRanges(const std::string &str) {
598     std::optional<std::pair<VideoSize, VideoSize>> range = VideoSize::ParseSizeRange(str);
599     if (!range) {
600         ALOGW("could not parse size range: %s", str.c_str());
601         return std::nullopt;
602     }
603 
604     return std::make_optional(std::pair(
605             Range(range.value().first.getWidth(), range.value().second.getWidth()),
606             Range(range.value().first.getHeight(), range.value().second.getHeight())));
607 }
608 
609 // static
EquivalentVP9Level(const sp<AMessage> & format)610 int32_t VideoCapabilities::EquivalentVP9Level(const sp<AMessage> &format) {
611     int32_t blockSizeWidth = 8;
612     int32_t blockSizeHeight = 8;
613     // VideoSize *blockSizePtr = &VideoSize(8, 8);
614     AString blockSizeStr;
615     if (format->findString("block-size", &blockSizeStr)) {
616         std::optional<VideoSize> parsedBlockSize
617                 = VideoSize::ParseSize(std::string(blockSizeStr.c_str()));
618         if (parsedBlockSize) {
619             // blockSize = parsedBlockSize.value();
620             blockSizeWidth = parsedBlockSize.value().getWidth();
621             blockSizeHeight = parsedBlockSize.value().getHeight();
622         }
623     }
624     int32_t BS = blockSizeWidth * blockSizeHeight;
625 
626     int32_t FS = 0;
627     AString blockCountRangeStr;
628     if (format->findString("block-count-range", &blockCountRangeStr)) {
629         std::optional<Range<int>> counts = Range<int32_t>::Parse(
630                 std::string(blockCountRangeStr.c_str()));
631         if (counts) {
632             FS = BS * counts.value().upper();
633         }
634     }
635 
636     int64_t SR = 0;
637     AString blockRatesStr;
638     if (format->findString("blocks-per-second-range", &blockRatesStr)) {
639         std::optional<Range<int64_t>> blockRates
640                 = Range<int64_t>::Parse(std::string(blockRatesStr.c_str()));
641         if (blockRates) {
642             // ToDo: Catch the potential overflow issue.
643             SR = BS * blockRates.value().upper();
644         }
645     }
646 
647     int32_t D = 0;
648     AString dimensionRangesStr;
649     if (format->findString("size-range", &dimensionRangesStr)) {
650         std::optional<std::pair<Range<int>, Range<int>>> dimensionRanges =
651                 ParseWidthHeightRanges(std::string(dimensionRangesStr.c_str()));
652         if (dimensionRanges) {
653             D = std::max(dimensionRanges.value().first.upper(),
654                     dimensionRanges.value().second.upper());
655         }
656     }
657 
658     int32_t BR = 0;
659     AString bitrateRangeStr;
660     if (format->findString("bitrate-range", &bitrateRangeStr)) {
661         std::optional<Range<int>> bitRates = Range<int32_t>::Parse(
662                 std::string(bitrateRangeStr.c_str()));
663         if (bitRates) {
664             BR = divUp(bitRates.value().upper(), 1000);
665         }
666     }
667 
668     if (SR <=      829440 && FS <=    36864 && BR <=    200 && D <=   512)
669         return VP9Level1;
670     if (SR <=     2764800 && FS <=    73728 && BR <=    800 && D <=   768)
671         return VP9Level11;
672     if (SR <=     4608000 && FS <=   122880 && BR <=   1800 && D <=   960)
673         return VP9Level2;
674     if (SR <=     9216000 && FS <=   245760 && BR <=   3600 && D <=  1344)
675         return VP9Level21;
676     if (SR <=    20736000 && FS <=   552960 && BR <=   7200 && D <=  2048)
677         return VP9Level3;
678     if (SR <=    36864000 && FS <=   983040 && BR <=  12000 && D <=  2752)
679         return VP9Level31;
680     if (SR <=    83558400 && FS <=  2228224 && BR <=  18000 && D <=  4160)
681         return VP9Level4;
682     if (SR <=   160432128 && FS <=  2228224 && BR <=  30000 && D <=  4160)
683         return VP9Level41;
684     if (SR <=   311951360 && FS <=  8912896 && BR <=  60000 && D <=  8384)
685         return VP9Level5;
686     if (SR <=   588251136 && FS <=  8912896 && BR <= 120000 && D <=  8384)
687         return VP9Level51;
688     if (SR <=  1176502272 && FS <=  8912896 && BR <= 180000 && D <=  8384)
689         return VP9Level52;
690     if (SR <=  1176502272 && FS <= 35651584 && BR <= 180000 && D <= 16832)
691         return VP9Level6;
692     if (SR <= 2353004544L && FS <= 35651584 && BR <= 240000 && D <= 16832)
693         return VP9Level61;
694     if (SR <= 4706009088L && FS <= 35651584 && BR <= 480000 && D <= 16832)
695         return VP9Level62;
696     // returning largest level
697     return VP9Level62;
698 }
699 
parseFromInfo(const sp<AMessage> & format)700 void VideoCapabilities::parseFromInfo(const sp<AMessage> &format) {
701     VideoSize blockSize = VideoSize(mBlockWidth, mBlockHeight);
702     VideoSize alignment = VideoSize(mWidthAlignment, mHeightAlignment);
703     std::optional<Range<int32_t>> counts, widths, heights;
704     std::optional<Range<int32_t>> frameRates, bitRates;
705     std::optional<Range<int64_t>> blockRates;
706     std::optional<Range<Rational>> ratios, blockRatios;
707 
708     AString blockSizeStr;
709     if (format->findString("block-size", &blockSizeStr)) {
710         std::optional<VideoSize> parsedBlockSize
711                 = VideoSize::ParseSize(std::string(blockSizeStr.c_str()));
712         blockSize = parsedBlockSize.value_or(blockSize);
713     }
714     AString alignmentStr;
715     if (format->findString("alignment", &alignmentStr)) {
716         std::optional<VideoSize> parsedAlignment
717             = VideoSize::ParseSize(std::string(alignmentStr.c_str()));
718         alignment = parsedAlignment.value_or(alignment);
719     }
720     AString blockCountRangeStr;
721     if (format->findString("block-count-range", &blockCountRangeStr)) {
722         std::optional<Range<int>> parsedBlockCountRange =
723                 Range<int32_t>::Parse(std::string(blockCountRangeStr.c_str()));
724         if (parsedBlockCountRange) {
725             counts = parsedBlockCountRange.value();
726         }
727     }
728     AString blockRatesStr;
729     if (format->findString("blocks-per-second-range", &blockRatesStr)) {
730         blockRates = Range<int64_t>::Parse(std::string(blockRatesStr.c_str()));
731     }
732     mMeasuredFrameRates = getMeasuredFrameRates(format);
733     mPerformancePoints = getPerformancePoints(format);
734     AString sizeRangesStr;
735     if (format->findString("size-range", &sizeRangesStr)) {
736         std::optional<std::pair<Range<int>, Range<int>>> sizeRanges =
737             ParseWidthHeightRanges(std::string(sizeRangesStr.c_str()));
738         if (sizeRanges) {
739             widths = sizeRanges.value().first;
740             heights = sizeRanges.value().second;
741         }
742     }
743     // for now this just means using the smaller max size as 2nd
744     // upper limit.
745     // for now we are keeping the profile specific "width/height
746     // in macroblocks" limits.
747     if (format->contains("feature-can-swap-width-height")) {
748         if (widths && heights) {
749             mSmallerDimensionUpperLimit =
750                 std::min(widths.value().upper(), heights.value().upper());
751             widths = heights = widths.value().extend(heights.value());
752         } else {
753             ALOGW("feature can-swap-width-height is best used with size-range");
754             mSmallerDimensionUpperLimit =
755                 std::min(mWidthRange.upper(), mHeightRange.upper());
756             mWidthRange = mHeightRange = mWidthRange.extend(mHeightRange);
757         }
758     }
759 
760     AString ratioStr;
761     if (format->findString("block-aspect-ratio-range", &ratioStr)) {
762         ratios = Rational::ParseRange(std::string(ratioStr.c_str()));
763     }
764     AString blockRatiosStr;
765     if (format->findString("pixel-aspect-ratio-range", &blockRatiosStr)) {
766         blockRatios = Rational::ParseRange(std::string(blockRatiosStr.c_str()));
767     }
768     AString frameRatesStr;
769     if (format->findString("frame-rate-range", &frameRatesStr)) {
770         frameRates = Range<int32_t>::Parse(std::string(frameRatesStr.c_str()));
771         if (frameRates) {
772             frameRates = frameRates.value().intersect(FRAME_RATE_RANGE);
773             if (frameRates.value().empty()) {
774                 ALOGW("frame rate range is out of limits");
775                 frameRates = std::nullopt;
776             }
777         }
778     }
779     AString bitRatesStr;
780     if (format->findString("bitrate-range", &bitRatesStr)) {
781         bitRates = Range<int32_t>::Parse(std::string(bitRatesStr.c_str()));
782         if (bitRates) {
783             bitRates = bitRates.value().intersect(BITRATE_RANGE);
784             if (bitRates.value().empty()) {
785                 ALOGW("bitrate range is out of limits");
786                 bitRates = std::nullopt;
787             }
788         }
789     }
790 
791     if (!IsPowerOfTwo(blockSize.getWidth()) || !IsPowerOfTwo(blockSize.getHeight())
792             || !IsPowerOfTwo(alignment.getWidth()) || !IsPowerOfTwo(alignment.getHeight())) {
793         ALOGE("The widths and heights of blockSizes and alignments must be the power of two."
794                 " blockSize width: %d; blockSize height: %d;"
795                 " alignment width: %d; alignment height: %d.",
796                 blockSize.getWidth(), blockSize.getHeight(),
797                 alignment.getWidth(), alignment.getHeight());
798         mError |= ERROR_CAPABILITIES_UNRECOGNIZED;
799         return;
800     }
801 
802     // update block-size and alignment
803     applyMacroBlockLimits(
804             INT32_MAX, INT32_MAX, INT32_MAX, INT64_MAX,
805             blockSize.getWidth(), blockSize.getHeight(),
806             alignment.getWidth(), alignment.getHeight());
807 
808     if ((mError & ERROR_CAPABILITIES_UNSUPPORTED) != 0 || mAllowMbOverride) {
809         // codec supports profiles that we don't know.
810         // Use supplied values clipped to platform limits
811         if (widths) {
812             mWidthRange = VideoSize::GetAllowedDimensionRange().intersect(widths.value());
813         }
814         if (heights) {
815             mHeightRange = VideoSize::GetAllowedDimensionRange().intersect(heights.value());
816         }
817         if (counts) {
818             mBlockCountRange = POSITIVE_INT32.intersect(
819                     counts.value().factor(mBlockWidth * mBlockHeight
820                             / blockSize.getWidth() / blockSize.getHeight()));
821         }
822         if (blockRates) {
823             mBlocksPerSecondRange = POSITIVE_INT64.intersect(
824                     blockRates.value().factor(mBlockWidth * mBlockHeight
825                             / blockSize.getWidth() / blockSize.getHeight()));
826         }
827         if (blockRatios) {
828             mBlockAspectRatioRange = POSITIVE_RATIONALS.intersect(
829                     Rational::ScaleRange(blockRatios.value(),
830                             mBlockHeight / blockSize.getHeight(),
831                             mBlockWidth / blockSize.getWidth()));
832         }
833         if (ratios) {
834             mAspectRatioRange = POSITIVE_RATIONALS.intersect(ratios.value());
835         }
836         if (frameRates) {
837             mFrameRateRange = FRAME_RATE_RANGE.intersect(frameRates.value());
838         }
839         if (bitRates) {
840             // only allow bitrate override if unsupported profiles were encountered
841             if ((mError & ERROR_CAPABILITIES_UNSUPPORTED) != 0) {
842                 mBitrateRange = BITRATE_RANGE.intersect(bitRates.value());
843             } else {
844                 mBitrateRange = mBitrateRange.intersect(bitRates.value());
845             }
846         }
847     } else {
848         // no unsupported profile/levels, so restrict values to known limits
849         if (widths) {
850             mWidthRange = mWidthRange.intersect(widths.value());
851         }
852         if (heights) {
853             mHeightRange = mHeightRange.intersect(heights.value());
854         }
855         if (counts) {
856             mBlockCountRange = mBlockCountRange.intersect(
857                     counts.value().factor(mBlockWidth * mBlockHeight
858                             / blockSize.getWidth() / blockSize.getHeight()));
859         }
860         if (blockRates) {
861             mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(
862                     blockRates.value().factor(mBlockWidth * mBlockHeight
863                             / blockSize.getWidth() / blockSize.getHeight()));
864         }
865         if (blockRatios) {
866             mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(
867                     Rational::ScaleRange(blockRatios.value(),
868                             mBlockHeight / blockSize.getHeight(),
869                             mBlockWidth / blockSize.getWidth()));
870         }
871         if (ratios) {
872             mAspectRatioRange = mAspectRatioRange.intersect(ratios.value());
873         }
874         if (frameRates) {
875             mFrameRateRange = mFrameRateRange.intersect(frameRates.value());
876         }
877         if (bitRates) {
878             mBitrateRange = mBitrateRange.intersect(bitRates.value());
879         }
880     }
881     updateLimits();
882 }
883 
applyBlockLimits(int32_t blockWidth,int32_t blockHeight,Range<int32_t> counts,Range<int64_t> rates,Range<Rational> ratios)884 void VideoCapabilities::applyBlockLimits(
885         int32_t blockWidth, int32_t blockHeight,
886         Range<int32_t> counts, Range<int64_t> rates, Range<Rational> ratios) {
887 
888     if (!IsPowerOfTwo(blockWidth) || !IsPowerOfTwo(blockHeight)) {
889         ALOGE("blockWidth and blockHeight must be the power of two."
890                 " blockWidth: %d; blockHeight: %d", blockWidth, blockHeight);
891         mError |= ERROR_CAPABILITIES_UNRECOGNIZED;
892         return;
893     }
894 
895     const int32_t newBlockWidth = std::max(blockWidth, mBlockWidth);
896     const int32_t newBlockHeight = std::max(blockHeight, mBlockHeight);
897 
898     // factor will always be a power-of-2
899     int32_t factor =
900         newBlockWidth * newBlockHeight / mBlockWidth / mBlockHeight;
901     if (factor != 1) {
902         mBlockCountRange = mBlockCountRange.factor(factor);
903         mBlocksPerSecondRange = mBlocksPerSecondRange.factor(factor);
904         mBlockAspectRatioRange = Rational::ScaleRange(
905                 mBlockAspectRatioRange,
906                 newBlockHeight / mBlockHeight,
907                 newBlockWidth / mBlockWidth);
908         mHorizontalBlockRange = mHorizontalBlockRange.factor(newBlockWidth / mBlockWidth);
909         mVerticalBlockRange = mVerticalBlockRange.factor(newBlockHeight / mBlockHeight);
910     }
911     factor = newBlockWidth * newBlockHeight / blockWidth / blockHeight;
912     if (factor != 1) {
913         counts = counts.factor(factor);
914         rates = rates.factor((int64_t)factor);
915         ratios = Rational::ScaleRange(
916                 ratios, newBlockHeight / blockHeight,
917                 newBlockWidth / blockWidth);
918     }
919     mBlockCountRange = mBlockCountRange.intersect(counts);
920     mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(rates);
921     mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(ratios);
922     mBlockWidth = newBlockWidth;
923     mBlockHeight = newBlockHeight;
924 }
925 
applyAlignment(int32_t widthAlignment,int32_t heightAlignment)926 void VideoCapabilities::applyAlignment(
927         int32_t widthAlignment, int32_t heightAlignment) {
928     if (!IsPowerOfTwo(widthAlignment) || !IsPowerOfTwo(heightAlignment)) {
929         ALOGE("width and height alignments must be the power of two."
930                 " widthAlignment: %d; heightAlignment: %d", widthAlignment, heightAlignment);
931         mError |= ERROR_CAPABILITIES_UNRECOGNIZED;
932         return;
933     }
934 
935     if (widthAlignment > mBlockWidth || heightAlignment > mBlockHeight) {
936         // maintain assumption that 0 < alignment <= block-size
937         applyBlockLimits(
938                 std::max(widthAlignment, mBlockWidth),
939                 std::max(heightAlignment, mBlockHeight),
940                 POSITIVE_INT32, POSITIVE_INT64, POSITIVE_RATIONALS);
941     }
942 
943     mWidthAlignment = std::max(widthAlignment, mWidthAlignment);
944     mHeightAlignment = std::max(heightAlignment, mHeightAlignment);
945 
946     mWidthRange = mWidthRange.align(mWidthAlignment);
947     mHeightRange = mHeightRange.align(mHeightAlignment);
948 }
949 
updateLimits()950 void VideoCapabilities::updateLimits() {
951     // pixels -> blocks <- counts
952     mHorizontalBlockRange = mHorizontalBlockRange.intersect(
953             mWidthRange.factor(mBlockWidth));
954     mHorizontalBlockRange = mHorizontalBlockRange.intersect(
955             Range(  mBlockCountRange.lower() / mVerticalBlockRange.upper(),
956                     mBlockCountRange.upper() / mVerticalBlockRange.lower()));
957     mVerticalBlockRange = mVerticalBlockRange.intersect(
958             mHeightRange.factor(mBlockHeight));
959     mVerticalBlockRange = mVerticalBlockRange.intersect(
960             Range(  mBlockCountRange.lower() / mHorizontalBlockRange.upper(),
961                     mBlockCountRange.upper() / mHorizontalBlockRange.lower()));
962     mBlockCountRange = mBlockCountRange.intersect(
963             Range(  mHorizontalBlockRange.lower()
964                             * mVerticalBlockRange.lower(),
965                     mHorizontalBlockRange.upper()
966                             * mVerticalBlockRange.upper()));
967     mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(
968             Rational(mHorizontalBlockRange.lower(), mVerticalBlockRange.upper()),
969             Rational(mHorizontalBlockRange.upper(), mVerticalBlockRange.lower()));
970 
971     // blocks -> pixels
972     mWidthRange = mWidthRange.intersect(
973             (mHorizontalBlockRange.lower() - 1) * mBlockWidth + mWidthAlignment,
974             mHorizontalBlockRange.upper() * mBlockWidth);
975     mHeightRange = mHeightRange.intersect(
976             (mVerticalBlockRange.lower() - 1) * mBlockHeight + mHeightAlignment,
977             mVerticalBlockRange.upper() * mBlockHeight);
978     mAspectRatioRange = mAspectRatioRange.intersect(
979             Rational(mWidthRange.lower(), mHeightRange.upper()),
980             Rational(mWidthRange.upper(), mHeightRange.lower()));
981 
982     mSmallerDimensionUpperLimit = std::min(
983             mSmallerDimensionUpperLimit,
984             std::min(mWidthRange.upper(), mHeightRange.upper()));
985 
986     // blocks -> rate
987     mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(
988             mBlockCountRange.lower() * (int64_t)mFrameRateRange.lower(),
989             mBlockCountRange.upper() * (int64_t)mFrameRateRange.upper());
990     mFrameRateRange = mFrameRateRange.intersect(
991             (int32_t)(mBlocksPerSecondRange.lower()
992                     / mBlockCountRange.upper()),
993             (int32_t)(mBlocksPerSecondRange.upper()
994                     / (double)mBlockCountRange.lower()));
995 }
996 
applyMacroBlockLimits(int32_t maxHorizontalBlocks,int32_t maxVerticalBlocks,int32_t maxBlocks,int64_t maxBlocksPerSecond,int32_t blockWidth,int32_t blockHeight,int32_t widthAlignment,int32_t heightAlignment)997 void VideoCapabilities::applyMacroBlockLimits(
998         int32_t maxHorizontalBlocks, int32_t maxVerticalBlocks,
999         int32_t maxBlocks, int64_t maxBlocksPerSecond,
1000         int32_t blockWidth, int32_t blockHeight,
1001         int32_t widthAlignment, int32_t heightAlignment) {
1002     applyMacroBlockLimits(
1003             1 /* minHorizontalBlocks */, 1 /* minVerticalBlocks */,
1004             maxHorizontalBlocks, maxVerticalBlocks,
1005             maxBlocks, maxBlocksPerSecond,
1006             blockWidth, blockHeight, widthAlignment, heightAlignment);
1007 }
1008 
applyMacroBlockLimits(int32_t minHorizontalBlocks,int32_t minVerticalBlocks,int32_t maxHorizontalBlocks,int32_t maxVerticalBlocks,int32_t maxBlocks,int64_t maxBlocksPerSecond,int32_t blockWidth,int32_t blockHeight,int32_t widthAlignment,int32_t heightAlignment)1009 void VideoCapabilities::applyMacroBlockLimits(
1010         int32_t minHorizontalBlocks, int32_t minVerticalBlocks,
1011         int32_t maxHorizontalBlocks, int32_t maxVerticalBlocks,
1012         int32_t maxBlocks, int64_t maxBlocksPerSecond,
1013         int32_t blockWidth, int32_t blockHeight,
1014         int32_t widthAlignment, int32_t heightAlignment) {
1015     applyAlignment(widthAlignment, heightAlignment);
1016     applyBlockLimits(
1017             blockWidth, blockHeight, Range((int32_t)1, maxBlocks),
1018             Range((int64_t)1, maxBlocksPerSecond),
1019             Range(Rational(1, maxVerticalBlocks), Rational(maxHorizontalBlocks, 1)));
1020     mHorizontalBlockRange =
1021             mHorizontalBlockRange.intersect(
1022                     divUp(minHorizontalBlocks, (mBlockWidth / blockWidth)),
1023                     maxHorizontalBlocks / (mBlockWidth / blockWidth));
1024     mVerticalBlockRange =
1025             mVerticalBlockRange.intersect(
1026                     divUp(minVerticalBlocks, (mBlockHeight / blockHeight)),
1027                     maxVerticalBlocks / (mBlockHeight / blockHeight));
1028 }
1029 
applyLevelLimits()1030 void VideoCapabilities::applyLevelLimits() {
1031     int64_t maxBlocksPerSecond = 0;
1032     int32_t maxBlocks = 0;
1033     int32_t maxBps = 0;
1034     int32_t maxDPBBlocks = 0;
1035 
1036     int errors = ERROR_CAPABILITIES_NONE_SUPPORTED;
1037     const char *mediaType = mMediaType.c_str();
1038     if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_VIDEO_AVC)) {
1039         maxBlocks = 99;
1040         maxBlocksPerSecond = 1485;
1041         maxBps = 64000;
1042         maxDPBBlocks = 396;
1043         for (ProfileLevel profileLevel: mProfileLevels) {
1044             int32_t MBPS = 0, FS = 0, BR = 0, DPB = 0;
1045             bool supported = true;
1046             switch (profileLevel.mLevel) {
1047                 case AVCLevel1:
1048                     MBPS =     1485; FS =     99; BR =     64; DPB =    396; break;
1049                 case AVCLevel1b:
1050                     MBPS =     1485; FS =     99; BR =    128; DPB =    396; break;
1051                 case AVCLevel11:
1052                     MBPS =     3000; FS =    396; BR =    192; DPB =    900; break;
1053                 case AVCLevel12:
1054                     MBPS =     6000; FS =    396; BR =    384; DPB =   2376; break;
1055                 case AVCLevel13:
1056                     MBPS =    11880; FS =    396; BR =    768; DPB =   2376; break;
1057                 case AVCLevel2:
1058                     MBPS =    11880; FS =    396; BR =   2000; DPB =   2376; break;
1059                 case AVCLevel21:
1060                     MBPS =    19800; FS =    792; BR =   4000; DPB =   4752; break;
1061                 case AVCLevel22:
1062                     MBPS =    20250; FS =   1620; BR =   4000; DPB =   8100; break;
1063                 case AVCLevel3:
1064                     MBPS =    40500; FS =   1620; BR =  10000; DPB =   8100; break;
1065                 case AVCLevel31:
1066                     MBPS =   108000; FS =   3600; BR =  14000; DPB =  18000; break;
1067                 case AVCLevel32:
1068                     MBPS =   216000; FS =   5120; BR =  20000; DPB =  20480; break;
1069                 case AVCLevel4:
1070                     MBPS =   245760; FS =   8192; BR =  20000; DPB =  32768; break;
1071                 case AVCLevel41:
1072                     MBPS =   245760; FS =   8192; BR =  50000; DPB =  32768; break;
1073                 case AVCLevel42:
1074                     MBPS =   522240; FS =   8704; BR =  50000; DPB =  34816; break;
1075                 case AVCLevel5:
1076                     MBPS =   589824; FS =  22080; BR = 135000; DPB = 110400; break;
1077                 case AVCLevel51:
1078                     MBPS =   983040; FS =  36864; BR = 240000; DPB = 184320; break;
1079                 case AVCLevel52:
1080                     MBPS =  2073600; FS =  36864; BR = 240000; DPB = 184320; break;
1081                 case AVCLevel6:
1082                     MBPS =  4177920; FS = 139264; BR = 240000; DPB = 696320; break;
1083                 case AVCLevel61:
1084                     MBPS =  8355840; FS = 139264; BR = 480000; DPB = 696320; break;
1085                 case AVCLevel62:
1086                     MBPS = 16711680; FS = 139264; BR = 800000; DPB = 696320; break;
1087                 default:
1088                     ALOGW("Unrecognized level %d for %s", profileLevel.mLevel, mediaType);
1089                     errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1090             }
1091             switch (profileLevel.mProfile) {
1092                 case AVCProfileConstrainedHigh:
1093                 case AVCProfileHigh:
1094                     BR *= 1250; break;
1095                 case AVCProfileHigh10:
1096                     BR *= 3000; break;
1097                 case AVCProfileExtended:
1098                 case AVCProfileHigh422:
1099                 case AVCProfileHigh444:
1100                     ALOGW("Unsupported profile %d for %s", profileLevel.mProfile, mediaType);
1101                     errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1102                     supported = false;
1103                     FALLTHROUGH_INTENDED;
1104                     // fall through - treat as base profile
1105                 case AVCProfileConstrainedBaseline:
1106                     FALLTHROUGH_INTENDED;
1107                 case AVCProfileBaseline:
1108                     FALLTHROUGH_INTENDED;
1109                 case AVCProfileMain:
1110                     BR *= 1000; break;
1111                 default:
1112                     ALOGW("Unrecognized profile %d for %s", profileLevel.mProfile, mediaType);
1113                     errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1114                     BR *= 1000;
1115             }
1116             if (supported) {
1117                 errors &= ~ERROR_CAPABILITIES_NONE_SUPPORTED;
1118             }
1119             maxBlocksPerSecond = std::max((int64_t)MBPS, maxBlocksPerSecond);
1120             maxBlocks = std::max(FS, maxBlocks);
1121             maxBps = std::max(BR, maxBps);
1122             maxDPBBlocks = std::max(maxDPBBlocks, DPB);
1123         }
1124 
1125         int32_t maxLengthInBlocks = (int32_t)(std::sqrt(8 * maxBlocks));
1126         applyMacroBlockLimits(
1127                 maxLengthInBlocks, maxLengthInBlocks,
1128                 maxBlocks, maxBlocksPerSecond,
1129                 16 /* blockWidth */, 16 /* blockHeight */,
1130                 1 /* widthAlignment */, 1 /* heightAlignment */);
1131     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_VIDEO_MPEG2)) {
1132         int32_t maxWidth = 11, maxHeight = 9, maxRate = 15;
1133         maxBlocks = 99;
1134         maxBlocksPerSecond = 1485;
1135         maxBps = 64000;
1136         for (ProfileLevel profileLevel: mProfileLevels) {
1137             int32_t MBPS = 0, FS = 0, BR = 0, FR = 0, W = 0, H = 0;
1138             bool supported = true;
1139             switch (profileLevel.mProfile) {
1140                 case MPEG2ProfileSimple:
1141                     switch (profileLevel.mLevel) {
1142                         case MPEG2LevelML:
1143                             FR = 30; W = 45; H =  36; MBPS =  40500; FS =  1620; BR =  15000; break;
1144                         default:
1145                             ALOGW("Unrecognized profile/level %d/%d for %s",
1146                                     profileLevel.mProfile, profileLevel.mLevel, mediaType);
1147                             errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1148                     }
1149                     break;
1150                 case MPEG2ProfileMain:
1151                     switch (profileLevel.mLevel) {
1152                         case MPEG2LevelLL:
1153                             FR = 30; W = 22; H =  18; MBPS =  11880; FS =   396; BR =  4000; break;
1154                         case MPEG2LevelML:
1155                             FR = 30; W = 45; H =  36; MBPS =  40500; FS =  1620; BR = 15000; break;
1156                         case MPEG2LevelH14:
1157                             FR = 60; W = 90; H =  68; MBPS = 183600; FS =  6120; BR = 60000; break;
1158                         case MPEG2LevelHL:
1159                             FR = 60; W = 120; H = 68; MBPS = 244800; FS =  8160; BR = 80000; break;
1160                         case MPEG2LevelHP:
1161                             FR = 60; W = 120; H = 68; MBPS = 489600; FS =  8160; BR = 80000; break;
1162                         default:
1163                             ALOGW("Unrecognized profile/level %d / %d for %s",
1164                                     profileLevel.mProfile, profileLevel.mLevel, mediaType);
1165                             errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1166                     }
1167                     break;
1168                 case MPEG2Profile422:
1169                 case MPEG2ProfileSNR:
1170                 case MPEG2ProfileSpatial:
1171                 case MPEG2ProfileHigh:
1172                     ALOGW("Unsupported profile %d for %s", profileLevel.mProfile, mediaType);
1173                     errors |= ERROR_CAPABILITIES_UNSUPPORTED;
1174                     supported = false;
1175                     break;
1176                 default:
1177                     ALOGW("Unrecognized profile %d for %s", profileLevel.mProfile, mediaType);
1178                     errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1179             }
1180             if (supported) {
1181                 errors &= ~ERROR_CAPABILITIES_NONE_SUPPORTED;
1182             }
1183             maxBlocksPerSecond = std::max((int64_t)MBPS, maxBlocksPerSecond);
1184             maxBlocks = std::max(FS, maxBlocks);
1185             maxBps = std::max(BR * 1000, maxBps);
1186             maxWidth = std::max(W, maxWidth);
1187             maxHeight = std::max(H, maxHeight);
1188             maxRate = std::max(FR, maxRate);
1189         }
1190         applyMacroBlockLimits(maxWidth, maxHeight,
1191                 maxBlocks, maxBlocksPerSecond,
1192                 16 /* blockWidth */, 16 /* blockHeight */,
1193                 1 /* widthAlignment */, 1 /* heightAlignment */);
1194         mFrameRateRange = mFrameRateRange.intersect(12, maxRate);
1195     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_VIDEO_MPEG4)) {
1196         int32_t maxWidth = 11, maxHeight = 9, maxRate = 15;
1197         maxBlocks = 99;
1198         maxBlocksPerSecond = 1485;
1199         maxBps = 64000;
1200         for (ProfileLevel profileLevel: mProfileLevels) {
1201             int32_t MBPS = 0, FS = 0, BR = 0, FR = 0, W = 0, H = 0;
1202             bool strict = false; // true: W, H and FR are individual max limits
1203             bool supported = true;
1204             switch (profileLevel.mProfile) {
1205                 case MPEG4ProfileSimple:
1206                     switch (profileLevel.mLevel) {
1207                         case MPEG4Level0:
1208                             strict = true;
1209                             FR = 15; W = 11; H =  9; MBPS =  1485; FS =  99; BR =  64; break;
1210                         case MPEG4Level1:
1211                             FR = 30; W = 11; H =  9; MBPS =  1485; FS =  99; BR =  64; break;
1212                         case MPEG4Level0b:
1213                             strict = true;
1214                             FR = 15; W = 11; H =  9; MBPS =  1485; FS =  99; BR = 128; break;
1215                         case MPEG4Level2:
1216                             FR = 30; W = 22; H = 18; MBPS =  5940; FS = 396; BR = 128; break;
1217                         case MPEG4Level3:
1218                             FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 384; break;
1219                         case MPEG4Level4a:
1220                             FR = 30; W = 40; H = 30; MBPS = 36000; FS = 1200; BR = 4000; break;
1221                         case MPEG4Level5:
1222                             FR = 30; W = 45; H = 36; MBPS = 40500; FS = 1620; BR = 8000; break;
1223                         case MPEG4Level6:
1224                             FR = 30; W = 80; H = 45; MBPS = 108000; FS = 3600; BR = 12000; break;
1225                         default:
1226                             ALOGW("Unrecognized profile/level %d/%d for %s",
1227                                     profileLevel.mProfile, profileLevel.mLevel, mediaType);
1228                             errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1229                     }
1230                     break;
1231                 case MPEG4ProfileAdvancedSimple:
1232                     switch (profileLevel.mLevel) {
1233                         case MPEG4Level0:
1234                         case MPEG4Level1:
1235                             FR = 30; W = 11; H =  9; MBPS =  2970; FS =   99; BR =  128; break;
1236                         case MPEG4Level2:
1237                             FR = 30; W = 22; H = 18; MBPS =  5940; FS =  396; BR =  384; break;
1238                         case MPEG4Level3:
1239                             FR = 30; W = 22; H = 18; MBPS = 11880; FS =  396; BR =  768; break;
1240                         case MPEG4Level3b:
1241                             FR = 30; W = 22; H = 18; MBPS = 11880; FS =  396; BR = 1500; break;
1242                         case MPEG4Level4:
1243                             FR = 30; W = 44; H = 36; MBPS = 23760; FS =  792; BR = 3000; break;
1244                         case MPEG4Level5:
1245                             FR = 30; W = 45; H = 36; MBPS = 48600; FS = 1620; BR = 8000; break;
1246                         default:
1247                             ALOGW("Unrecognized profile/level %d/%d for %s",
1248                                     profileLevel.mProfile, profileLevel.mLevel, mediaType);
1249                             errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1250                     }
1251                     break;
1252                 case MPEG4ProfileMain:             // 2-4
1253                 case MPEG4ProfileNbit:             // 2
1254                 case MPEG4ProfileAdvancedRealTime: // 1-4
1255                 case MPEG4ProfileCoreScalable:     // 1-3
1256                 case MPEG4ProfileAdvancedCoding:   // 1-4
1257                 case MPEG4ProfileCore:             // 1-2
1258                 case MPEG4ProfileAdvancedCore:     // 1-4
1259                 case MPEG4ProfileSimpleScalable:   // 0-2
1260                 case MPEG4ProfileHybrid:           // 1-2
1261 
1262                 // Studio profiles are not supported by our codecs.
1263 
1264                 // Only profiles that can decode simple object types are considered.
1265                 // The following profiles are not able to.
1266                 case MPEG4ProfileBasicAnimated:    // 1-2
1267                 case MPEG4ProfileScalableTexture:  // 1
1268                 case MPEG4ProfileSimpleFace:       // 1-2
1269                 case MPEG4ProfileAdvancedScalable: // 1-3
1270                 case MPEG4ProfileSimpleFBA:        // 1-2
1271                     ALOGV("Unsupported profile %d for %s", profileLevel.mProfile, mediaType);
1272                     errors |= ERROR_CAPABILITIES_UNSUPPORTED;
1273                     supported = false;
1274                     break;
1275                 default:
1276                     ALOGW("Unrecognized profile %d for %s", profileLevel.mProfile, mediaType);
1277                     errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1278             }
1279             if (supported) {
1280                 errors &= ~ERROR_CAPABILITIES_NONE_SUPPORTED;
1281             }
1282             maxBlocksPerSecond = std::max((int64_t)MBPS, maxBlocksPerSecond);
1283             maxBlocks = std::max(FS, maxBlocks);
1284             maxBps = std::max(BR * 1000, maxBps);
1285             if (strict) {
1286                 maxWidth = std::max(W, maxWidth);
1287                 maxHeight = std::max(H, maxHeight);
1288                 maxRate = std::max(FR, maxRate);
1289             } else {
1290                 // assuming max 60 fps frame rate and 1:2 aspect ratio
1291                 int32_t maxDim = (int32_t)std::sqrt(2 * FS);
1292                 maxWidth = std::max(maxDim, maxWidth);
1293                 maxHeight = std::max(maxDim, maxHeight);
1294                 maxRate = std::max(std::max(FR, 60), maxRate);
1295             }
1296         }
1297         applyMacroBlockLimits(maxWidth, maxHeight,
1298                 maxBlocks, maxBlocksPerSecond,
1299                 16 /* blockWidth */, 16 /* blockHeight */,
1300                 1 /* widthAlignment */, 1 /* heightAlignment */);
1301         mFrameRateRange = mFrameRateRange.intersect(12, maxRate);
1302     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_VIDEO_H263)) {
1303         int32_t maxWidth = 11, maxHeight = 9, maxRate = 15;
1304         int32_t minWidth = maxWidth, minHeight = maxHeight;
1305         int32_t minAlignment = 16;
1306         maxBlocks = 99;
1307         maxBlocksPerSecond = 1485;
1308         maxBps = 64000;
1309         for (ProfileLevel profileLevel: mProfileLevels) {
1310             int32_t MBPS = 0, BR = 0, FR = 0, W = 0, H = 0, minW = minWidth, minH = minHeight;
1311             bool strict = false; // true: support only sQCIF, QCIF (maybe CIF)
1312             switch (profileLevel.mLevel) {
1313                 case H263Level10:
1314                     strict = true; // only supports sQCIF & QCIF
1315                     FR = 15; W = 11; H =  9; BR =   1; MBPS =  W * H * FR; break;
1316                 case H263Level20:
1317                     strict = true; // only supports sQCIF, QCIF & CIF
1318                     FR = 30; W = 22; H = 18; BR =   2; MBPS =  W * H * 15; break;
1319                 case H263Level30:
1320                     strict = true; // only supports sQCIF, QCIF & CIF
1321                     FR = 30; W = 22; H = 18; BR =   6; MBPS =  W * H * FR; break;
1322                 case H263Level40:
1323                     strict = true; // only supports sQCIF, QCIF & CIF
1324                     FR = 30; W = 22; H = 18; BR =  32; MBPS =  W * H * FR; break;
1325                 case H263Level45:
1326                     // only implies level 10 support
1327                     strict = profileLevel.mProfile == H263ProfileBaseline
1328                             || profileLevel.mProfile ==
1329                                     H263ProfileBackwardCompatible;
1330                     if (!strict) {
1331                         minW = 1; minH = 1; minAlignment = 4;
1332                     }
1333                     FR = 15; W = 11; H =  9; BR =   2; MBPS =  W * H * FR; break;
1334                 case H263Level50:
1335                     // only supports 50fps for H > 15
1336                     minW = 1; minH = 1; minAlignment = 4;
1337                     FR = 60; W = 22; H = 18; BR =  64; MBPS =  W * H * 50; break;
1338                 case H263Level60:
1339                     // only supports 50fps for H > 15
1340                     minW = 1; minH = 1; minAlignment = 4;
1341                     FR = 60; W = 45; H = 18; BR = 128; MBPS =  W * H * 50; break;
1342                 case H263Level70:
1343                     // only supports 50fps for H > 30
1344                     minW = 1; minH = 1; minAlignment = 4;
1345                     FR = 60; W = 45; H = 36; BR = 256; MBPS =  W * H * 50; break;
1346                 default:
1347                     ALOGW("Unrecognized profile/level %d/%d for %s",
1348                             profileLevel.mProfile, profileLevel.mLevel, mediaType);
1349                     errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1350             }
1351             switch (profileLevel.mProfile) {
1352                 case H263ProfileBackwardCompatible:
1353                 case H263ProfileBaseline:
1354                 case H263ProfileH320Coding:
1355                 case H263ProfileHighCompression:
1356                 case H263ProfileHighLatency:
1357                 case H263ProfileInterlace:
1358                 case H263ProfileInternet:
1359                 case H263ProfileISWV2:
1360                 case H263ProfileISWV3:
1361                     break;
1362                 default:
1363                     ALOGW("Unrecognized profile %d for %s", profileLevel.mProfile, mediaType);
1364                     errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1365             }
1366             if (strict) {
1367                 // Strict levels define sub-QCIF min size and enumerated sizes. We cannot
1368                 // express support for "only sQCIF & QCIF (& CIF)" using VideoCapabilities
1369                 // but we can express "only QCIF (& CIF)", so set minimume size at QCIF.
1370                 // minW = 8; minH = 6;
1371                 minW = 11; minH = 9;
1372             } else {
1373                 // any support for non-strict levels (including unrecognized profiles or
1374                 // levels) allow custom frame size support beyond supported limits
1375                 // (other than bitrate)
1376                 mAllowMbOverride = true;
1377             }
1378             errors &= ~ERROR_CAPABILITIES_NONE_SUPPORTED;
1379             maxBlocksPerSecond = std::max((int64_t)MBPS, maxBlocksPerSecond);
1380             maxBlocks = std::max(W * H, maxBlocks);
1381             maxBps = std::max(BR * 64000, maxBps);
1382             maxWidth = std::max(W, maxWidth);
1383             maxHeight = std::max(H, maxHeight);
1384             maxRate = std::max(FR, maxRate);
1385             minWidth = std::min(minW, minWidth);
1386             minHeight = std::min(minH, minHeight);
1387         }
1388         // unless we encountered custom frame size support, limit size to QCIF and CIF
1389         // using aspect ratio.
1390         if (!mAllowMbOverride) {
1391             mBlockAspectRatioRange =
1392                 Range(Rational(11, 9), Rational(11, 9));
1393         }
1394         applyMacroBlockLimits(
1395                 minWidth, minHeight,
1396                 maxWidth, maxHeight,
1397                 maxBlocks, maxBlocksPerSecond,
1398                 16 /* blockWidth */, 16 /* blockHeight */,
1399                 minAlignment /* widthAlignment */, minAlignment /* heightAlignment */);
1400         mFrameRateRange = Range(1, maxRate);
1401     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_VIDEO_VP8)) {
1402         maxBlocks = INT_MAX;
1403         maxBlocksPerSecond = INT_MAX;
1404 
1405         // TODO: set to 100Mbps for now, need a number for VP8
1406         maxBps = 100000000;
1407 
1408         // profile levels are not indicative for VPx, but verify
1409         // them nonetheless
1410         for (ProfileLevel profileLevel: mProfileLevels) {
1411             switch (profileLevel.mLevel) {
1412                 case VP8Level_Version0:
1413                 case VP8Level_Version1:
1414                 case VP8Level_Version2:
1415                 case VP8Level_Version3:
1416                     break;
1417                 default:
1418                     ALOGW("Unrecognized level %d for %s", profileLevel.mLevel, mediaType);
1419                     errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1420             }
1421             switch (profileLevel.mProfile) {
1422                 case VP8ProfileMain:
1423                     break;
1424                 default:
1425                     ALOGW("Unrecognized profile %d for %s", profileLevel.mProfile, mediaType);
1426                     errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1427             }
1428             errors &= ~ERROR_CAPABILITIES_NONE_SUPPORTED;
1429         }
1430 
1431         const int32_t blockSize = 16;
1432         applyMacroBlockLimits(SHRT_MAX, SHRT_MAX,
1433                 maxBlocks, maxBlocksPerSecond, blockSize, blockSize,
1434                 1 /* widthAlignment */, 1 /* heightAlignment */);
1435     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_VIDEO_VP9)) {
1436         maxBlocksPerSecond = 829440;
1437         maxBlocks = 36864;
1438         maxBps = 200000;
1439         int32_t maxDim = 512;
1440 
1441         for (ProfileLevel profileLevel: mProfileLevels) {
1442             int64_t SR = 0; // luma sample rate
1443             int32_t FS = 0;  // luma picture size
1444             int32_t BR = 0;  // bit rate kbps
1445             int32_t D = 0;   // luma dimension
1446             switch (profileLevel.mLevel) {
1447                 case VP9Level1:
1448                     SR =      829440; FS =    36864; BR =    200; D =   512; break;
1449                 case VP9Level11:
1450                     SR =     2764800; FS =    73728; BR =    800; D =   768; break;
1451                 case VP9Level2:
1452                     SR =     4608000; FS =   122880; BR =   1800; D =   960; break;
1453                 case VP9Level21:
1454                     SR =     9216000; FS =   245760; BR =   3600; D =  1344; break;
1455                 case VP9Level3:
1456                     SR =    20736000; FS =   552960; BR =   7200; D =  2048; break;
1457                 case VP9Level31:
1458                     SR =    36864000; FS =   983040; BR =  12000; D =  2752; break;
1459                 case VP9Level4:
1460                     SR =    83558400; FS =  2228224; BR =  18000; D =  4160; break;
1461                 case VP9Level41:
1462                     SR =   160432128; FS =  2228224; BR =  30000; D =  4160; break;
1463                 case VP9Level5:
1464                     SR =   311951360; FS =  8912896; BR =  60000; D =  8384; break;
1465                 case VP9Level51:
1466                     SR =   588251136; FS =  8912896; BR = 120000; D =  8384; break;
1467                 case VP9Level52:
1468                     SR =  1176502272; FS =  8912896; BR = 180000; D =  8384; break;
1469                 case VP9Level6:
1470                     SR =  1176502272; FS = 35651584; BR = 180000; D = 16832; break;
1471                 case VP9Level61:
1472                     SR = 2353004544L; FS = 35651584; BR = 240000; D = 16832; break;
1473                 case VP9Level62:
1474                     SR = 4706009088L; FS = 35651584; BR = 480000; D = 16832; break;
1475                 default:
1476                     ALOGW("Unrecognized level %d for %s", profileLevel.mLevel, mediaType);
1477                     errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1478             }
1479             switch (profileLevel.mProfile) {
1480                 case VP9Profile0:
1481                 case VP9Profile1:
1482                 case VP9Profile2:
1483                 case VP9Profile3:
1484                 case VP9Profile2HDR:
1485                 case VP9Profile3HDR:
1486                 case VP9Profile2HDR10Plus:
1487                 case VP9Profile3HDR10Plus:
1488                     break;
1489                 default:
1490                     ALOGW("Unrecognized profile %d for %s", profileLevel.mProfile, mediaType);
1491                     errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1492             }
1493             errors &= ~ERROR_CAPABILITIES_NONE_SUPPORTED;
1494             maxBlocksPerSecond = std::max(SR, maxBlocksPerSecond);
1495             maxBlocks = std::max(FS, maxBlocks);
1496             maxBps = std::max(BR * 1000, maxBps);
1497             maxDim = std::max(D, maxDim);
1498         }
1499 
1500         const int32_t blockSize = 8;
1501         int32_t maxLengthInBlocks = divUp(maxDim, blockSize);
1502         maxBlocks = divUp(maxBlocks, blockSize * blockSize);
1503         maxBlocksPerSecond = divUp(maxBlocksPerSecond, blockSize * (int64_t)blockSize);
1504 
1505         applyMacroBlockLimits(
1506                 maxLengthInBlocks, maxLengthInBlocks,
1507                 maxBlocks, maxBlocksPerSecond,
1508                 blockSize, blockSize,
1509                 1 /* widthAlignment */, 1 /* heightAlignment */);
1510     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_VIDEO_HEVC)) {
1511         // CTBs are at least 8x8 so use 8x8 block size
1512         maxBlocks = 36864 >> 6; // 192x192 pixels == 576 8x8 blocks
1513         maxBlocksPerSecond = maxBlocks * 15;
1514         maxBps = 128000;
1515         for (ProfileLevel profileLevel: mProfileLevels) {
1516             double FR = 0;
1517             int32_t FS = 0, BR = 0;
1518             switch (profileLevel.mLevel) {
1519                 /* The HEVC spec talks only in a very convoluted manner about the
1520                     existence of levels 1-3.1 for High tier, which could also be
1521                     understood as 'decoders and encoders should treat these levels
1522                     as if they were Main tier', so we do that. */
1523                 case HEVCMainTierLevel1:
1524                 case HEVCHighTierLevel1:
1525                     FR =    15; FS =    36864; BR =    128; break;
1526                 case HEVCMainTierLevel2:
1527                 case HEVCHighTierLevel2:
1528                     FR =    30; FS =   122880; BR =   1500; break;
1529                 case HEVCMainTierLevel21:
1530                 case HEVCHighTierLevel21:
1531                     FR =    30; FS =   245760; BR =   3000; break;
1532                 case HEVCMainTierLevel3:
1533                 case HEVCHighTierLevel3:
1534                     FR =    30; FS =   552960; BR =   6000; break;
1535                 case HEVCMainTierLevel31:
1536                 case HEVCHighTierLevel31:
1537                     FR = 33.75; FS =   983040; BR =  10000; break;
1538                 case HEVCMainTierLevel4:
1539                     FR =    30; FS =  2228224; BR =  12000; break;
1540                 case HEVCHighTierLevel4:
1541                     FR =    30; FS =  2228224; BR =  30000; break;
1542                 case HEVCMainTierLevel41:
1543                     FR =    60; FS =  2228224; BR =  20000; break;
1544                 case HEVCHighTierLevel41:
1545                     FR =    60; FS =  2228224; BR =  50000; break;
1546                 case HEVCMainTierLevel5:
1547                     FR =    30; FS =  8912896; BR =  25000; break;
1548                 case HEVCHighTierLevel5:
1549                     FR =    30; FS =  8912896; BR = 100000; break;
1550                 case HEVCMainTierLevel51:
1551                     FR =    60; FS =  8912896; BR =  40000; break;
1552                 case HEVCHighTierLevel51:
1553                     FR =    60; FS =  8912896; BR = 160000; break;
1554                 case HEVCMainTierLevel52:
1555                     FR =   120; FS =  8912896; BR =  60000; break;
1556                 case HEVCHighTierLevel52:
1557                     FR =   120; FS =  8912896; BR = 240000; break;
1558                 case HEVCMainTierLevel6:
1559                     FR =    30; FS = 35651584; BR =  60000; break;
1560                 case HEVCHighTierLevel6:
1561                     FR =    30; FS = 35651584; BR = 240000; break;
1562                 case HEVCMainTierLevel61:
1563                     FR =    60; FS = 35651584; BR = 120000; break;
1564                 case HEVCHighTierLevel61:
1565                     FR =    60; FS = 35651584; BR = 480000; break;
1566                 case HEVCMainTierLevel62:
1567                     FR =   120; FS = 35651584; BR = 240000; break;
1568                 case HEVCHighTierLevel62:
1569                     FR =   120; FS = 35651584; BR = 800000; break;
1570                 default:
1571                     ALOGW("Unrecognized level %d for %s", profileLevel.mLevel, mediaType);
1572                     errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1573             }
1574             switch (profileLevel.mProfile) {
1575                 case HEVCProfileMain:
1576                 case HEVCProfileMain10:
1577                 case HEVCProfileMainStill:
1578                 case HEVCProfileMain10HDR10:
1579                 case HEVCProfileMain10HDR10Plus:
1580                     break;
1581                 default:
1582                     ALOGW("Unrecognized profile %d for %s", profileLevel.mProfile, mediaType);
1583                     errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1584             }
1585 
1586             /* DPB logic:
1587             if      (width * height <= FS / 4)    DPB = 16;
1588             else if (width * height <= FS / 2)    DPB = 12;
1589             else if (width * height <= FS * 0.75) DPB = 8;
1590             else                                  DPB = 6;
1591             */
1592 
1593             FS >>= 6; // convert pixels to blocks
1594             errors &= ~ERROR_CAPABILITIES_NONE_SUPPORTED;
1595             maxBlocksPerSecond = std::max((int64_t)(FR * FS), maxBlocksPerSecond);
1596             maxBlocks = std::max(FS, maxBlocks);
1597             maxBps = std::max(1000 * BR, maxBps);
1598         }
1599 
1600         int32_t maxLengthInBlocks = (int32_t)(std::sqrt(8 * maxBlocks));
1601         applyMacroBlockLimits(
1602                 maxLengthInBlocks, maxLengthInBlocks,
1603                 maxBlocks, maxBlocksPerSecond,
1604                 8 /* blockWidth */, 8 /* blockHeight */,
1605                 1 /* widthAlignment */, 1 /* heightAlignment */);
1606     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_VIDEO_AV1)) {
1607         maxBlocksPerSecond = 829440;
1608         maxBlocks = 36864;
1609         maxBps = 200000;
1610         int32_t maxDim = 512;
1611 
1612         // Sample rate, Picture Size, Bit rate and luma dimension for AV1 Codec,
1613         // corresponding to the definitions in
1614         // "AV1 Bitstream & Decoding Process Specification", Annex A
1615         // found at https://aomedia.org/av1-bitstream-and-decoding-process-specification/
1616         for (ProfileLevel profileLevel: mProfileLevels) {
1617             int64_t SR = 0; // luma sample rate
1618             int32_t FS = 0;  // luma picture size
1619             int32_t BR = 0;  // bit rate kbps
1620             int32_t D = 0;   // luma D
1621             switch (profileLevel.mLevel) {
1622                 case AV1Level2:
1623                     SR =     5529600; FS =   147456; BR =   1500; D =  2048; break;
1624                 case AV1Level21:
1625                 case AV1Level22:
1626                 case AV1Level23:
1627                     SR =    10454400; FS =   278784; BR =   3000; D =  2816; break;
1628 
1629                 case AV1Level3:
1630                     SR =    24969600; FS =   665856; BR =   6000; D =  4352; break;
1631                 case AV1Level31:
1632                 case AV1Level32:
1633                 case AV1Level33:
1634                     SR =    39938400; FS =  1065024; BR =  10000; D =  5504; break;
1635 
1636                 case AV1Level4:
1637                     SR =    77856768; FS =  2359296; BR =  12000; D =  6144; break;
1638                 case AV1Level41:
1639                 case AV1Level42:
1640                 case AV1Level43:
1641                     SR =   155713536; FS =  2359296; BR =  20000; D =  6144; break;
1642 
1643                 case AV1Level5:
1644                     SR =   273715200; FS =  8912896; BR =  30000; D =  8192; break;
1645                 case AV1Level51:
1646                     SR =   547430400; FS =  8912896; BR =  40000; D =  8192; break;
1647                 case AV1Level52:
1648                     SR =  1094860800; FS =  8912896; BR =  60000; D =  8192; break;
1649                 case AV1Level53:
1650                     SR =  1176502272; FS =  8912896; BR =  60000; D =  8192; break;
1651 
1652                 case AV1Level6:
1653                     SR =  1176502272; FS = 35651584; BR =  60000; D = 16384; break;
1654                 case AV1Level61:
1655                     SR = 2189721600L; FS = 35651584; BR = 100000; D = 16384; break;
1656                 case AV1Level62:
1657                     SR = 4379443200L; FS = 35651584; BR = 160000; D = 16384; break;
1658                 case AV1Level63:
1659                     SR = 4706009088L; FS = 35651584; BR = 160000; D = 16384; break;
1660 
1661                 default:
1662                     ALOGW("Unrecognized level %d for %s", profileLevel.mLevel, mediaType);
1663                     errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1664             }
1665             switch (profileLevel.mProfile) {
1666                 case AV1ProfileMain8:
1667                 case AV1ProfileMain10:
1668                 case AV1ProfileMain10HDR10:
1669                 case AV1ProfileMain10HDR10Plus:
1670                     break;
1671                 default:
1672                     ALOGW("Unrecognized profile %d for %s", profileLevel.mProfile, mediaType);
1673                     errors |= ERROR_CAPABILITIES_UNRECOGNIZED;
1674             }
1675             errors &= ~ERROR_CAPABILITIES_NONE_SUPPORTED;
1676             maxBlocksPerSecond = std::max(SR, maxBlocksPerSecond);
1677             maxBlocks = std::max(FS, maxBlocks);
1678             maxBps = std::max(BR * 1000, maxBps);
1679             maxDim = std::max(D, maxDim);
1680         }
1681 
1682         const int32_t blockSize = 8;
1683         int32_t maxLengthInBlocks = divUp(maxDim, blockSize);
1684         maxBlocks = divUp(maxBlocks, blockSize * blockSize);
1685         maxBlocksPerSecond = divUp(maxBlocksPerSecond, blockSize * (int64_t)blockSize);
1686         applyMacroBlockLimits(
1687                 maxLengthInBlocks, maxLengthInBlocks,
1688                 maxBlocks, maxBlocksPerSecond,
1689                 blockSize, blockSize,
1690                 1 /* widthAlignment */, 1 /* heightAlignment */);
1691     } else {
1692         ALOGW("Unsupported mime %s", mediaType);
1693         // using minimal bitrate here.  should be overridden by
1694         // info from media_codecs.xml
1695         maxBps = 64000;
1696         errors |= ERROR_CAPABILITIES_UNSUPPORTED;
1697     }
1698     mBitrateRange = Range(1, maxBps);
1699     mError |= errors;
1700 }
1701 
1702 }  // namespace android