blob: 961f676127eec00da9a1b04e47f464eec49d1dee [file] [log] [blame]
Ray Essick1831f7b2021-03-15 16:10:51 -07001/*
2 * Copyright 2021, 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 "CodecProperties"
19#include <utils/Log.h>
20
21#include <string>
Ray Essicka727ef92021-03-29 13:35:02 -070022#include <stdlib.h>
Ray Essick1831f7b2021-03-15 16:10:51 -070023
24#include <media/formatshaper/CodecProperties.h>
25
26namespace android {
27namespace mediaformatshaper {
28
29CodecProperties::CodecProperties(std::string name, std::string mediaType) {
Ray Essick970f1c82021-03-25 13:37:45 -070030 ALOGV("CodecProperties(%s, %s)", name.c_str(), mediaType.c_str());
Ray Essick1831f7b2021-03-15 16:10:51 -070031 mName = name;
32 mMediaType = mediaType;
33}
34
35std::string CodecProperties::getName(){
36 return mName;
37}
38
39std::string CodecProperties::getMediaType(){
40 return mMediaType;
41}
42
43int CodecProperties::supportedMinimumQuality() {
44 return mMinimumQuality;
45}
46void CodecProperties::setSupportedMinimumQuality(int vmaf) {
47 mMinimumQuality = vmaf;
48}
49
50int CodecProperties::targetQpMax() {
51 return mTargetQpMax;
52}
53void CodecProperties::setTargetQpMax(int qpMax) {
54 mTargetQpMax = qpMax;
55}
56
57// what API is this codec set up for (e.g. API of the associated partition)
58// vendor-side (OEM) codecs may be older, due to 'vendor freeze' and treble
59int CodecProperties::supportedApi() {
60 return mApi;
61}
62
Ray Essick970f1c82021-03-25 13:37:45 -070063void CodecProperties::setFeatureValue(std::string key, int32_t value) {
64 ALOGD("setFeatureValue(%s,%d)", key.c_str(), value);
65 mFeatures.insert({key, value});
66
Ray Essicka727ef92021-03-29 13:35:02 -070067 if (!strcmp(key.c_str(), "qp-bounds")) { // official key
Ray Essick970f1c82021-03-25 13:37:45 -070068 setSupportsQp(1);
Ray Essicka727ef92021-03-29 13:35:02 -070069 } else if (!strcmp(key.c_str(), "vq-supports-qp")) { // key from prototyping
Ray Essick970f1c82021-03-25 13:37:45 -070070 setSupportsQp(1);
Ray Essicka727ef92021-03-29 13:35:02 -070071 } else if (!strcmp(key.c_str(), "vq-minimum-quality")) {
72 setSupportedMinimumQuality(1);
Ray Essick970f1c82021-03-25 13:37:45 -070073 }
74}
75
76bool CodecProperties::getFeatureValue(std::string key, int32_t *valuep) {
77 ALOGV("getFeatureValue(%s)", key.c_str());
78 if (valuep == nullptr) {
79 return false;
80 }
81 auto mapped = mFeatures.find(key);
82 if (mapped != mFeatures.end()) {
83 *valuep = mapped->second;
84 return true;
85 }
86 return false;
87}
88
Ray Essicka727ef92021-03-29 13:35:02 -070089// Tuning values (which differ from Features)
90// this is where we set up things like target bitrates and QP ranges
91// NB the tuning values arrive as a string, allowing us to convert it into an appropriate
92// format (int, float, ranges, other combinations)
93//
94void CodecProperties::setTuningValue(std::string key, std::string value) {
95 ALOGD("setTuningValue(%s,%s)", key.c_str(), value.c_str());
96 mTunings.insert({key, value});
97
98 bool legal = false;
99 // NB: old school strtol() because std::stoi() throws exceptions
100 if (!strcmp(key.c_str(), "vq-target-qpmax")) {
101 const char *p = value.c_str();
102 char *q;
103 int32_t iValue = strtol(p, &q, 0);
104 if (q != p) {
105 setTargetQpMax(iValue);
106 legal = true;
107 }
108 } else if (!strcmp(key.c_str(), "vq-target-bpp")) {
109 const char *p = value.c_str();
110 char *q;
111 double bpp = strtod(p, &q);
112 if (q != p) {
113 setBpp(bpp);
114 legal = true;
115 }
116 } else if (!strcmp(key.c_str(), "vq-target-bppx100")) {
117 const char *p = value.c_str();
118 char *q;
119 int32_t iValue = strtol(p, &q, 0);
120 if (q != p) {
121 double bpp = iValue / 100.0;
122 setBpp(bpp);
123 legal = true;
124 }
125 } else {
126 legal = true;
127 }
128
129 if (!legal) {
130 ALOGW("setTuningValue() unable to apply tuning '%s' with value '%s'",
131 key.c_str(), value.c_str());
132 }
133 return;
134}
135
136bool CodecProperties::getTuningValue(std::string key, std::string &value) {
137 ALOGV("getTuningValue(%s)", key.c_str());
138 auto mapped = mFeatures.find(key);
139 if (mapped != mFeatures.end()) {
140 value = mapped->second;
141 return true;
142 }
143 return false;
144}
145
Ray Essick970f1c82021-03-25 13:37:45 -0700146
Ray Essick1831f7b2021-03-15 16:10:51 -0700147std::string CodecProperties::getMapping(std::string key, std::string kind) {
148 ALOGV("getMapping(key %s, kind %s )", key.c_str(), kind.c_str());
149 //play with mMappings
150 auto mapped = mMappings.find(kind + "-" + key);
151 if (mapped != mMappings.end()) {
152 std::string result = mapped->second;
153 ALOGV("getMapping(%s, %s) -> %s", key.c_str(), kind.c_str(), result.c_str());
154 return result;
155 }
156 ALOGV("nope, return unchanged key");
157 return key;
158}
159
160
161// really a bit of debugging code here.
162void CodecProperties::showMappings() {
163 ALOGD("Mappings:");
164 int count = 0;
165 for (const auto& [key, value] : mMappings) {
166 count++;
167 ALOGD("'%s' -> '%s'", key.c_str(), value.c_str());
168 }
169 ALOGD("total %d mappings", count);
170}
171
172void CodecProperties::setMapping(std::string kind, std::string key, std::string value) {
173 ALOGV("setMapping(%s,%s,%s)", kind.c_str(), key.c_str(), value.c_str());
174 std::string metaKey = kind + "-" + key;
175 mMappings.insert({metaKey, value});
176}
177
178const char **CodecProperties::getMappings(std::string kind, bool reverse) {
179 ALOGV("getMappings(kind %s, reverse %d", kind.c_str(), reverse);
180 // how many do we need?
181 int count = mMappings.size();
182 if (count == 0) {
183 ALOGV("empty mappings");
184 return nullptr;
185 }
186 size_t size = sizeof(char *) * (2 * count + 2);
187 const char **result = (const char **)malloc(size);
188 if (result == nullptr) {
189 ALOGW("no memory to return mappings");
190 return nullptr;
191 }
192 memset(result, '\0', size);
193
194 const char **pp = result;
195 for (const auto& [key, value] : mMappings) {
196 // split out the kind/key
197 size_t pos = key.find('-');
198 if (pos == std::string::npos) {
199 ALOGD("ignoring malformed key: %s", key.c_str());
200 continue;
201 }
202 std::string actualKind = key.substr(0,pos);
203 if (kind.length() != 0 && kind != actualKind) {
204 ALOGD("kinds don't match: want '%s' got '%s'", kind.c_str(), actualKind.c_str());
205 continue;
206 }
207 if (reverse) {
208 // codec specific -> std aka 'unmapping'
209 pp[0] = strdup( value.c_str());
210 pp[1] = strdup( key.substr(pos+1).c_str());
211 } else {
212 // std -> codec specific
213 pp[0] = strdup( key.substr(pos+1).c_str());
214 pp[1] = strdup( value.c_str());
215 }
216 ALOGV(" %s -> %s", pp[0], pp[1]);
217 pp += 2;
218 }
219
220 pp[0] = nullptr;
221 pp[1] = nullptr;
222
223 return result;
224}
225
226
227} // namespace mediaformatshaper
228} // namespace android
229