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