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