1 /*
2  * Copyright (C) 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 "FormatShaper"
19 #include <utils/Log.h>
20 
21 #include <string>
22 #include <inttypes.h>
23 
24 #include <media/NdkMediaFormat.h>
25 
26 #include "CodecProperties.h"
27 #include "VideoShaper.h"
28 #include "VQops.h"
29 
30 #include <media/formatshaper/FormatShaper.h>
31 
32 namespace android {
33 namespace mediaformatshaper {
34 
35 //
36 // Caller retains ownership of and responsibility for inFormat
37 //
38 
39 //
40 // the interface to the outside
41 //
42 
shapeFormat(shaperHandle_t shaper,AMediaFormat * inFormat,int flags)43 int shapeFormat(shaperHandle_t shaper, AMediaFormat* inFormat, int flags) {
44     CodecProperties *codec = (CodecProperties*) shaper;
45     if (codec == nullptr) {
46         return -1;
47     }
48     if (!codec->isRegistered()) {
49         return -1;
50     }
51 
52     // run through the list of possible transformations
53     //
54 
55     std::string mediaType = codec->getMediaType();
56     if (strncmp(mediaType.c_str(), "video/", 6) == 0) {
57         // video specific shaping
58         (void) videoShaper(codec, inFormat, flags);
59 
60     } else if (strncmp(mediaType.c_str(), "audio/", 6) == 0) {
61         // audio specific shaping
62 
63     } else {
64         ALOGV("unknown mediatype '%s', left untouched", mediaType.c_str());
65 
66     }
67 
68     return 0;
69 }
70 
setMap(shaperHandle_t shaper,const char * kind,const char * key,const char * value)71 int setMap(shaperHandle_t shaper,  const char *kind, const char *key, const char *value) {
72     ALOGV("setMap: kind %s key %s -> value %s", kind, key, value);
73     CodecProperties *codec = (CodecProperties*) shaper;
74     if (codec == nullptr) {
75         return -1;
76     }
77     // must not yet be registered
78     if (codec->isRegistered()) {
79         return -1;
80     }
81 
82     codec->setMapping(kind, key, value);
83     return 0;
84 }
85 
setFeature(shaperHandle_t shaper,const char * feature,int value)86 int setFeature(shaperHandle_t shaper, const char *feature, int value) {
87     ALOGV("set_feature: feature %s value %d", feature, value);
88     CodecProperties *codec = (CodecProperties*) shaper;
89     if (codec == nullptr) {
90         return -1;
91     }
92     // must not yet be registered
93     if (codec->isRegistered()) {
94         return -1;
95     }
96 
97     // save a map of all features
98     codec->setFeatureValue(feature, value);
99 
100     return 0;
101 }
102 
setTuning(shaperHandle_t shaper,const char * tuning,const char * value)103 int setTuning(shaperHandle_t shaper, const char *tuning, const char *value) {
104     ALOGV("setTuning: tuning %s value %s", tuning, value);
105     CodecProperties *codec = (CodecProperties*) shaper;
106     if (codec == nullptr) {
107         return -1;
108     }
109     // must not yet be registered
110     if (codec->isRegistered()) {
111         return -1;
112     }
113 
114     // save a map of all features
115     codec->setTuningValue(tuning, value);
116 
117     return 0;
118 }
119 
120 /*
121  * The routines that manage finding, creating, and registering the shapers.
122  */
123 
findShaper(const char * codecName,const char * mediaType)124 shaperHandle_t findShaper(const char *codecName, const char *mediaType) {
125     CodecProperties *codec = findCodec(codecName, mediaType);
126     return (shaperHandle_t) codec;
127 }
128 
createShaper(const char * codecName,const char * mediaType)129 shaperHandle_t createShaper(const char *codecName, const char *mediaType) {
130     CodecProperties *codec = new CodecProperties(codecName, mediaType);
131     if (codec != nullptr) {
132         codec->Seed();
133     }
134     return (shaperHandle_t) codec;
135 }
136 
registerShaper(shaperHandle_t shaper,const char * codecName,const char * mediaType)137 shaperHandle_t registerShaper(shaperHandle_t shaper, const char *codecName, const char *mediaType) {
138     ALOGV("registerShaper(handle, codecName %s, mediaType %s", codecName, mediaType);
139     CodecProperties *codec = (CodecProperties*) shaper;
140     if (codec == nullptr) {
141         return nullptr;
142     }
143     // must not yet be registered
144     if (codec->isRegistered()) {
145         return nullptr;
146     }
147 
148     // any final cleanup for the parameters. This allows us to override
149     // bad parameters from a devices XML file.
150     codec->Finish();
151 
152     // may return a different codec, if we lost a race.
153     // if so, registerCodec() reclaims the one we tried to register for us.
154     codec = registerCodec(codec, codecName, mediaType);
155     return (shaperHandle_t) codec;
156 }
157 
158 // mapping & unmapping
159 // give me the mappings for 'kind'.
160 // kind==null (or empty string), means *all* mappings
161 
getMappings(shaperHandle_t shaper,const char * kind)162 const char **getMappings(shaperHandle_t shaper, const char *kind) {
163     CodecProperties *codec = (CodecProperties*) shaper;
164     if (codec == nullptr)
165         return nullptr;
166     if (kind == nullptr)
167         kind = "";
168 
169     return codec->getMappings(kind, /* reverse */ false);
170 }
171 
getReverseMappings(shaperHandle_t shaper,const char * kind)172 const char **getReverseMappings(shaperHandle_t shaper, const char *kind) {
173     CodecProperties *codec = (CodecProperties*) shaper;
174     if (codec == nullptr)
175         return nullptr;
176     if (kind == nullptr)
177         kind = "";
178 
179     return codec->getMappings(kind, /* reverse */ true);
180 }
181 
182 
183 // the system grabs this structure
184 __attribute__ ((visibility ("default")))
185 extern "C" FormatShaperOps_t shaper_ops = {
186     .version = SHAPER_VERSION_V1,
187 
188     .findShaper = findShaper,
189     .createShaper = createShaper,
190     .setMap = setMap,
191     .setFeature = setFeature,
192     .registerShaper = registerShaper,
193 
194     .shapeFormat = shapeFormat,
195     .getMappings = getMappings,
196     .getReverseMappings = getReverseMappings,
197 
198     .setTuning = setTuning,
199 };
200 
201 }  // namespace mediaformatshaper
202 }  // namespace android
203 
204