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