blob: a8402208129b3432c80b9a7e481233f94cc0e558 [file] [log] [blame]
Songyue Hana034e242024-04-25 23:31:56 +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 "EncoderCapabilities"
19
20#include <android-base/strings.h>
21
22#include <media/CodecCapabilities.h>
23#include <media/EncoderCapabilities.h>
24#include <media/stagefright/MediaCodecConstants.h>
25
26namespace android {
27
28const Range<int>& EncoderCapabilities::getQualityRange() {
29 return mQualityRange;
30}
31
32const Range<int>& EncoderCapabilities::getComplexityRange() {
33 return mComplexityRange;
34}
35
36// static
37int EncoderCapabilities::ParseBitrateMode(std::string mode) {
38 for (Feature feat: sBitrateModes) {
39 if (base::EqualsIgnoreCase(feat.mName, mode)) {
40 return feat.mValue;
41 }
42 }
43 return 0;
44}
45
46bool EncoderCapabilities::isBitrateModeSupported(int mode) {
47 for (Feature feat : sBitrateModes) {
48 if (mode == feat.mValue) {
49 return (mBitControl & (1 << mode)) != 0;
50 }
51 }
52 return false;
53}
54
55// static
56std::shared_ptr<EncoderCapabilities> EncoderCapabilities::Create(std::string mediaType,
57 std::vector<ProfileLevel> profLevs, const sp<AMessage> &format) {
58 std::shared_ptr<EncoderCapabilities> caps(new EncoderCapabilities());
59 caps->init(mediaType, profLevs, format);
60 return caps;
61}
62
63void EncoderCapabilities::init(std::string mediaType, std::vector<ProfileLevel> profLevs,
64 const sp<AMessage> &format) {
65 // no support for complexity or quality yet
66 mMediaType = mediaType;
67 mProfileLevels = profLevs;
68 mComplexityRange = Range(0, 0);
69 mQualityRange = Range(0, 0);
70 mBitControl = (1 << BITRATE_MODE_VBR);
71
72 applyLevelLimits();
73 parseFromInfo(format);
74}
75
76void EncoderCapabilities::applyLevelLimits() {
77 if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_FLAC)) {
78 mComplexityRange = Range(0, 8);
79 mBitControl = (1 << BITRATE_MODE_CQ);
80 } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AMR_NB)
81 || base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AMR_WB)
82 || base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_G711_ALAW)
83 || base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_G711_MLAW)
84 || base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_MSGSM)) {
85 mBitControl = (1 << BITRATE_MODE_CBR);
86 }
87}
88
89void EncoderCapabilities::parseFromInfo(const sp<AMessage> &format) {
90 AString complexityRangeAStr;
91 if (format->findString("complexity-range", &complexityRangeAStr)) {
92 std::optional<Range<int>> complexityRangeOpt
93 = Range<int32_t>::Parse(std::string(complexityRangeAStr.c_str()));
94 mComplexityRange = complexityRangeOpt.value_or(mComplexityRange);
95 // TODO should we limit this to level limits?
96 }
97 AString qualityRangeAStr;
98 if (format->findString("quality-range", &qualityRangeAStr)) {
99 std::optional<Range<int>> qualityRangeOpt
100 = Range<int32_t>::Parse(std::string(qualityRangeAStr.c_str()));
101 mQualityRange = qualityRangeOpt.value_or(mQualityRange);
102 }
103 AString bitrateModesAStr;
104 if (format->findString("feature-bitrate-modes", &bitrateModesAStr)) {
105 mBitControl = 0;
106 for (std::string mode: base::Split(std::string(bitrateModesAStr.c_str()), ",")) {
107 mBitControl |= (1 << ParseBitrateMode(mode));
108 }
109 }
110 format->findInt32("complexity-default", &mDefaultComplexity);
111 format->findInt32("quality-default", &mDefaultQuality);
112 AString qualityScaleAStr;
113 if (format->findString("quality-scale", &qualityScaleAStr)) {
114 mQualityScale = std::string(qualityScaleAStr.c_str());
115 }
116}
117
118bool EncoderCapabilities::supports(
119 std::optional<int> complexity, std::optional<int> quality, std::optional<int> profile) {
120 bool ok = true;
121 if (complexity) {
122 ok &= mComplexityRange.contains(complexity.value());
123 }
124 if (quality) {
125 ok &= mQualityRange.contains(quality.value());
126 }
127 if (profile) {
128 ok &= std::any_of(mProfileLevels.begin(), mProfileLevels.end(),
129 [&profile](ProfileLevel pl){ return pl.mProfile == profile.value(); });
130 }
131 return ok;
132}
133
134void EncoderCapabilities::getDefaultFormat(sp<AMessage> &format) {
135 // don't list trivial quality/complexity as default for now
136 if (mQualityRange.upper() != mQualityRange.lower()
137 && mDefaultQuality != 0) {
138 format->setInt32(KEY_QUALITY, mDefaultQuality);
139 }
140 if (mComplexityRange.upper() != mComplexityRange.lower()
141 && mDefaultComplexity != 0) {
142 format->setInt32(KEY_COMPLEXITY, mDefaultComplexity);
143 }
144 // bitrates are listed in order of preference
145 for (Feature feat : sBitrateModes) {
146 if ((mBitControl & (1 << feat.mValue)) != 0) {
147 format->setInt32(KEY_BITRATE_MODE, feat.mValue);
148 break;
149 }
150 }
151}
152
153bool EncoderCapabilities::supportsFormat(const sp<AMessage> &format) {
154 int32_t mode;
155 if (format->findInt32(KEY_BITRATE_MODE, &mode) && !isBitrateModeSupported(mode)) {
156 return false;
157 }
158
159 int tmp;
160 std::optional<int> complexity = std::nullopt;
161 if (format->findInt32(KEY_COMPLEXITY, &tmp)) {
162 complexity = tmp;
163 }
164
165 if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_FLAC)) {
166 int flacComplexity;
167 if (format->findInt32(KEY_FLAC_COMPRESSION_LEVEL, &flacComplexity)) {
168 if (!complexity) {
169 complexity = flacComplexity;
170 } else if (flacComplexity != complexity.value()) {
171 ALOGE("Conflicting values for complexity and flac-compression-level,"
172 " which are %d and %d", complexity.value(), flacComplexity);
173 return false;
174 }
175 }
176 }
177
178 // other audio parameters
179 std::optional<int> profile = std::nullopt;
180 if (format->findInt32(KEY_PROFILE, &tmp)) {
181 profile = tmp;
182 }
183
184 if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AAC)) {
185 int aacProfile;
186 if (format->findInt32(KEY_AAC_PROFILE, &aacProfile)) {
187 if (!profile) {
188 profile = aacProfile;
189 } else if (aacProfile != profile.value()) {
190 ALOGE("Conflicting values for profile and aac-profile, which are %d and %d",
191 profile.value(), aacProfile);
192 return false;
193 }
194 }
195 }
196
197 std::optional<int> quality = std::nullopt;
198 if (format->findInt32(KEY_QUALITY, &tmp)) {
199 quality = tmp;
200 }
201
202 return supports(complexity, quality, profile);
203}
204
205} // namespace android