blob: 7f7cecaa1ae93e2da7674e26086007f69c97c937 [file] [log] [blame]
Pawin Vongmasa36653902018-11-15 00:10:25 -08001/*
2 * Copyright 2018 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
Pawin Vongmasae55ed3f2018-11-28 03:39:57 -080018#define LOG_TAG "CodecServiceRegistrant"
19
20#include <android-base/logging.h>
Pawin Vongmasa0c16dbe2019-12-16 04:25:41 -080021#include <android-base/properties.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080022
Pawin Vongmasa0c16dbe2019-12-16 04:25:41 -080023#include <C2Component.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080024#include <C2PlatformSupport.h>
25#include <codec2/hidl/1.0/ComponentStore.h>
Pawin Vongmasa0c16dbe2019-12-16 04:25:41 -080026#include <codec2/hidl/1.0/Configurable.h>
27#include <codec2/hidl/1.0/types.h>
28#include <hidl/HidlSupport.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080029#include <media/CodecServiceRegistrant.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080030
Pawin Vongmasa0c16dbe2019-12-16 04:25:41 -080031namespace /* unnamed */ {
32
33using ::android::hardware::hidl_vec;
34using ::android::hardware::hidl_string;
35using ::android::hardware::Return;
36using ::android::hardware::Void;
37using ::android::sp;
38using namespace ::android::hardware::media::c2::V1_0;
39using namespace ::android::hardware::media::c2::V1_0::utils;
40
41constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
42
43// Converter from IComponentStore to C2ComponentStore.
44class H2C2ComponentStore : public C2ComponentStore {
45protected:
46 sp<IComponentStore> mStore;
47 sp<IConfigurable> mConfigurable;
48public:
49 explicit H2C2ComponentStore(sp<IComponentStore> const& store)
50 : mStore{store},
51 mConfigurable{[store]() -> sp<IConfigurable>{
52 if (!store) {
53 return nullptr;
54 }
55 Return<sp<IConfigurable>> transResult =
56 store->getConfigurable();
57 return transResult.isOk() ?
58 static_cast<sp<IConfigurable>>(transResult) :
59 nullptr;
60 }()} {
61 if (!mConfigurable) {
62 LOG(ERROR) << "Preferred store is corrupted.";
63 }
64 }
65
66 virtual ~H2C2ComponentStore() override = default;
67
68 virtual c2_status_t config_sm(
69 std::vector<C2Param*> const &params,
70 std::vector<std::unique_ptr<C2SettingResult>>* const failures
71 ) override {
72 Params hidlParams;
73 if (!createParamsBlob(&hidlParams, params)) {
74 LOG(ERROR) << "config -- bad input.";
75 return C2_TRANSACTION_FAILED;
76 }
77 c2_status_t status{};
78 Return<void> transResult = mConfigurable->config(
79 hidlParams,
80 true,
81 [&status, &params, failures](
82 Status s,
83 const hidl_vec<SettingResult> f,
84 const Params& o) {
85 status = static_cast<c2_status_t>(s);
86 if (status != C2_OK && status != C2_BAD_INDEX) {
87 LOG(DEBUG) << "config -- call failed: "
88 << status << ".";
89 }
90 size_t i = failures->size();
91 failures->resize(i + f.size());
92 for (const SettingResult& sf : f) {
93 if (!objcpy(&(*failures)[i++], sf)) {
94 LOG(ERROR) << "config -- "
95 << "invalid SettingResult returned.";
96 return;
97 }
98 }
99 if (!updateParamsFromBlob(params, o)) {
100 LOG(ERROR) << "config -- "
101 << "failed to parse returned params.";
102 status = C2_CORRUPTED;
103 }
104 });
105 if (!transResult.isOk()) {
106 LOG(ERROR) << "config -- transaction failed.";
107 return C2_TRANSACTION_FAILED;
108 }
109 return status;
110 };
111
112 virtual c2_status_t copyBuffer(
113 std::shared_ptr<C2GraphicBuffer>,
114 std::shared_ptr<C2GraphicBuffer>) override {
115 LOG(ERROR) << "copyBuffer -- not supported.";
116 return C2_OMITTED;
117 }
118
119 virtual c2_status_t createComponent(
120 C2String, std::shared_ptr<C2Component> *const component) override {
121 component->reset();
122 LOG(ERROR) << "createComponent -- not supported.";
123 return C2_OMITTED;
124 }
125
126 virtual c2_status_t createInterface(
127 C2String, std::shared_ptr<C2ComponentInterface> *const interface) {
128 interface->reset();
129 LOG(ERROR) << "createInterface -- not supported.";
130 return C2_OMITTED;
131 }
132
133 virtual c2_status_t query_sm(
134 const std::vector<C2Param *> &stackParams,
135 const std::vector<C2Param::Index> &heapParamIndices,
136 std::vector<std::unique_ptr<C2Param>> *const heapParams) const
137 override {
138 hidl_vec<ParamIndex> indices(
139 stackParams.size() + heapParamIndices.size());
140 size_t numIndices = 0;
141 for (C2Param* const& stackParam : stackParams) {
142 if (!stackParam) {
143 LOG(WARNING) << "query -- null stack param encountered.";
144 continue;
145 }
146 indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
147 }
148 size_t numStackIndices = numIndices;
149 for (const C2Param::Index& index : heapParamIndices) {
150 indices[numIndices++] =
151 static_cast<ParamIndex>(static_cast<uint32_t>(index));
152 }
153 indices.resize(numIndices);
154 if (heapParams) {
155 heapParams->reserve(heapParams->size() + numIndices);
156 }
157 c2_status_t status;
158 Return<void> transResult = mConfigurable->query(
159 indices,
160 true,
161 [&status, &numStackIndices, &stackParams, heapParams](
162 Status s, const Params& p) {
163 status = static_cast<c2_status_t>(s);
164 if (status != C2_OK && status != C2_BAD_INDEX) {
165 LOG(DEBUG) << "query -- call failed: "
166 << status << ".";
167 return;
168 }
169 std::vector<C2Param*> paramPointers;
170 if (!parseParamsBlob(&paramPointers, p)) {
171 LOG(ERROR) << "query -- error while parsing params.";
172 status = C2_CORRUPTED;
173 return;
174 }
175 size_t i = 0;
176 for (auto it = paramPointers.begin();
177 it != paramPointers.end(); ) {
178 C2Param* paramPointer = *it;
179 if (numStackIndices > 0) {
180 --numStackIndices;
181 if (!paramPointer) {
182 LOG(WARNING) << "query -- null stack param.";
183 ++it;
184 continue;
185 }
186 for (; i < stackParams.size() && !stackParams[i]; ) {
187 ++i;
188 }
189 if (i >= stackParams.size()) {
190 LOG(ERROR) << "query -- unexpected error.";
191 status = C2_CORRUPTED;
192 return;
193 }
194 if (stackParams[i]->index() != paramPointer->index()) {
195 LOG(WARNING) << "query -- param skipped: "
196 "index = "
197 << stackParams[i]->index() << ".";
198 stackParams[i++]->invalidate();
199 continue;
200 }
201 if (!stackParams[i++]->updateFrom(*paramPointer)) {
202 LOG(WARNING) << "query -- param update failed: "
203 "index = "
204 << paramPointer->index() << ".";
205 }
206 } else {
207 if (!paramPointer) {
208 LOG(WARNING) << "query -- null heap param.";
209 ++it;
210 continue;
211 }
212 if (!heapParams) {
213 LOG(WARNING) << "query -- "
214 "unexpected extra stack param.";
215 } else {
216 heapParams->emplace_back(
217 C2Param::Copy(*paramPointer));
218 }
219 }
220 ++it;
221 }
222 });
223 if (!transResult.isOk()) {
224 LOG(ERROR) << "query -- transaction failed.";
225 return C2_TRANSACTION_FAILED;
226 }
227 return status;
228 }
229
230 virtual c2_status_t querySupportedParams_nb(
231 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
232 c2_status_t status;
233 Return<void> transResult = mConfigurable->querySupportedParams(
234 std::numeric_limits<uint32_t>::min(),
235 std::numeric_limits<uint32_t>::max(),
236 [&status, params](
237 Status s,
238 const hidl_vec<ParamDescriptor>& p) {
239 status = static_cast<c2_status_t>(s);
240 if (status != C2_OK) {
241 LOG(DEBUG) << "querySupportedParams -- call failed: "
242 << status << ".";
243 return;
244 }
245 size_t i = params->size();
246 params->resize(i + p.size());
247 for (const ParamDescriptor& sp : p) {
248 if (!objcpy(&(*params)[i++], sp)) {
249 LOG(ERROR) << "querySupportedParams -- "
250 << "invalid returned ParamDescriptor.";
251 return;
252 }
253 }
254 });
255 if (!transResult.isOk()) {
256 LOG(ERROR) << "querySupportedParams -- transaction failed.";
257 return C2_TRANSACTION_FAILED;
258 }
259 return status;
260 }
261
262 virtual c2_status_t querySupportedValues_sm(
263 std::vector<C2FieldSupportedValuesQuery> &fields) const {
264 hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
265 for (size_t i = 0; i < fields.size(); ++i) {
266 if (!objcpy(&inFields[i], fields[i])) {
267 LOG(ERROR) << "querySupportedValues -- bad input";
268 return C2_TRANSACTION_FAILED;
269 }
270 }
271
272 c2_status_t status;
273 Return<void> transResult = mConfigurable->querySupportedValues(
274 inFields,
275 true,
276 [&status, &inFields, &fields](
277 Status s,
278 const hidl_vec<FieldSupportedValuesQueryResult>& r) {
279 status = static_cast<c2_status_t>(s);
280 if (status != C2_OK) {
281 LOG(DEBUG) << "querySupportedValues -- call failed: "
282 << status << ".";
283 return;
284 }
285 if (r.size() != fields.size()) {
286 LOG(ERROR) << "querySupportedValues -- "
287 "input and output lists "
288 "have different sizes.";
289 status = C2_CORRUPTED;
290 return;
291 }
292 for (size_t i = 0; i < fields.size(); ++i) {
293 if (!objcpy(&fields[i], inFields[i], r[i])) {
294 LOG(ERROR) << "querySupportedValues -- "
295 "invalid returned value.";
296 status = C2_CORRUPTED;
297 return;
298 }
299 }
300 });
301 if (!transResult.isOk()) {
302 LOG(ERROR) << "querySupportedValues -- transaction failed.";
303 return C2_TRANSACTION_FAILED;
304 }
305 return status;
306 }
307
308 virtual C2String getName() const {
309 C2String outName;
310 Return<void> transResult = mConfigurable->getName(
311 [&outName](const hidl_string& name) {
312 outName = name.c_str();
313 });
314 if (!transResult.isOk()) {
315 LOG(ERROR) << "getName -- transaction failed.";
316 }
317 return outName;
318 }
319
320 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const
321 override {
322 struct SimpleParamReflector : public C2ParamReflector {
323 virtual std::unique_ptr<C2StructDescriptor> describe(
324 C2Param::CoreIndex coreIndex) const {
325 hidl_vec<ParamIndex> indices(1);
326 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
327 std::unique_ptr<C2StructDescriptor> descriptor;
328 Return<void> transResult = mBase->getStructDescriptors(
329 indices,
330 [&descriptor](
331 Status s,
332 const hidl_vec<StructDescriptor>& sd) {
333 c2_status_t status = static_cast<c2_status_t>(s);
334 if (status != C2_OK) {
335 LOG(DEBUG) << "SimpleParamReflector -- "
336 "getStructDescriptors() failed: "
337 << status << ".";
338 descriptor.reset();
339 return;
340 }
341 if (sd.size() != 1) {
342 LOG(DEBUG) << "SimpleParamReflector -- "
343 "getStructDescriptors() "
344 "returned vector of size "
345 << sd.size() << ". "
346 "It should be 1.";
347 descriptor.reset();
348 return;
349 }
350 if (!objcpy(&descriptor, sd[0])) {
351 LOG(DEBUG) << "SimpleParamReflector -- "
352 "getStructDescriptors() returned "
353 "corrupted data.";
354 descriptor.reset();
355 return;
356 }
357 });
358 return descriptor;
359 }
360
361 explicit SimpleParamReflector(sp<IComponentStore> base)
362 : mBase(base) { }
363
364 sp<IComponentStore> mBase;
365 };
366
367 return std::make_shared<SimpleParamReflector>(mStore);
368 }
369
370 virtual std::vector<std::shared_ptr<const C2Component::Traits>>
371 listComponents() override {
372 LOG(ERROR) << "listComponents -- not supported.";
373 return {};
374 }
375};
376
377bool ionPropertiesDefined() {
378 using namespace ::android::base;
379 std::string heapMask =
380 GetProperty("ro.com.android.media.swcodec.ion.heapmask", "undefined");
381 std::string flags =
382 GetProperty("ro.com.android.media.swcodec.ion.flags", "undefined");
383 std::string align =
384 GetProperty("ro.com.android.media.swcodec.ion.align", "undefined");
385 if (heapMask != "undefined" ||
386 flags != "undefined" ||
387 align != "undefined") {
388 LOG(INFO)
389 << "Some system properties for mediaswcodec ION usage are set: "
390 << "heapmask = " << heapMask << ", "
391 << "flags = " << flags << ", "
392 << "align = " << align << ". "
393 << "Preferred Codec2 store is defaulted to \"software\".";
394 return true;
395 }
396 return false;
397}
398
399} // unnamed namespace
400
Pawin Vongmasa36653902018-11-15 00:10:25 -0800401extern "C" void RegisterCodecServices() {
Pawin Vongmasa0c16dbe2019-12-16 04:25:41 -0800402 using ComponentStore = ::android::hardware::media::c2::V1_0::utils::
403 ComponentStore;
Pawin Vongmasae55ed3f2018-11-28 03:39:57 -0800404 LOG(INFO) << "Creating software Codec2 service...";
Pawin Vongmasa0c16dbe2019-12-16 04:25:41 -0800405 sp<ComponentStore> store =
406 new ComponentStore(::android::GetCodec2PlatformComponentStore());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800407 if (store == nullptr) {
Pawin Vongmasae55ed3f2018-11-28 03:39:57 -0800408 LOG(ERROR) <<
409 "Cannot create software Codec2 service.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800410 } else {
Pawin Vongmasa0c16dbe2019-12-16 04:25:41 -0800411 if (!ionPropertiesDefined()) {
412 std::string preferredStoreName = "default";
413 sp<IComponentStore> preferredStore =
414 IComponentStore::getService(preferredStoreName.c_str());
415 if (preferredStore) {
416 ::android::SetPreferredCodec2ComponentStore(
417 std::make_shared<H2C2ComponentStore>(preferredStore));
418 LOG(INFO) <<
419 "Preferred Codec2 store is set to \"" <<
420 preferredStoreName << "\".";
421 } else {
422 LOG(INFO) <<
423 "Preferred Codec2 store is defaulted to \"software\".";
424 }
425 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800426 if (store->registerAsService("software") != android::OK) {
Pawin Vongmasae55ed3f2018-11-28 03:39:57 -0800427 LOG(ERROR) <<
428 "Cannot register software Codec2 service.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800429 } else {
Pawin Vongmasae55ed3f2018-11-28 03:39:57 -0800430 LOG(INFO) <<
431 "Software Codec2 service created.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800432 }
433 }
434}
435