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