xref: /aosp_15_r20/frameworks/av/media/libmedia/EncoderCapabilities.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright 2024, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "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 
26 namespace android {
27 
getQualityRange()28 const Range<int>& EncoderCapabilities::getQualityRange() {
29     return mQualityRange;
30 }
31 
getComplexityRange()32 const Range<int>& EncoderCapabilities::getComplexityRange() {
33     return mComplexityRange;
34 }
35 
36 // static
ParseBitrateMode(std::string mode)37 int 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 
isBitrateModeSupported(int mode)46 bool 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
Create(std::string mediaType,std::vector<ProfileLevel> profLevs,const sp<AMessage> & format)56 std::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 
init(std::string mediaType,std::vector<ProfileLevel> profLevs,const sp<AMessage> & format)63 void 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 
applyLevelLimits()76 void 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 
parseFromInfo(const sp<AMessage> & format)89 void 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 
supports(std::optional<int> complexity,std::optional<int> quality,std::optional<int> profile)118 bool 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 
getDefaultFormat(sp<AMessage> & format)134 void 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 
supportsFormat(const sp<AMessage> & format)153 bool 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