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