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