1 /*
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 #ifndef CODEC2_COMMON_PARAM_TYPES_H
18 #define CODEC2_COMMON_PARAM_TYPES_H
19
20 #ifndef LOG_TAG
21 #define LOG_TAG "Codec2-ParamTypes"
22 #endif
23 #include <android-base/logging.h>
24
25 #include <log/log_safetynet.h>
26 #include <media/stagefright/foundation/AUtils.h>
27
28 #include <C2Component.h>
29 #include <C2Param.h>
30 #include <C2ParamInternal.h>
31 #include <util/C2ParamUtils.h>
32
33 #include <algorithm>
34 #include <unordered_map>
35
36 namespace android {
37
38 template <typename EnumClass>
underlying_value(EnumClass x)39 typename std::underlying_type<EnumClass>::type underlying_value(EnumClass x) {
40 return static_cast<typename std::underlying_type<EnumClass>::type>(x);
41 }
42
43 template <typename Common, typename DstVector, typename SrcVector>
copyVector(DstVector * d,const SrcVector & s)44 void copyVector(DstVector* d, const SrcVector& s) {
45 static_assert(sizeof(Common) == sizeof(decltype((*d)[0])),
46 "DstVector's component size does not match Common");
47 static_assert(sizeof(Common) == sizeof(decltype(s[0])),
48 "SrcVector's component size does not match Common");
49 d->resize(s.size());
50 std::copy(
51 reinterpret_cast<const Common*>(&s[0]),
52 reinterpret_cast<const Common*>(&s[0] + s.size()),
53 reinterpret_cast<Common*>(&(*d)[0]));
54 }
55
56 // {offset, size} -> FieldId
57 template <typename FieldId>
SetFieldId(FieldId * d,uint32_t offset,uint32_t size)58 void SetFieldId(FieldId *d, uint32_t offset, uint32_t size) {
59 d->offset = offset;
60 d->size = size;
61 }
62
63 // FieldId -> offset
64 template <typename FieldId>
GetOffsetFromFieldId(const FieldId & s)65 uint32_t GetOffsetFromFieldId(const FieldId &s) {
66 return s.offset;
67 }
68
69 // FieldId -> size
70 template <typename FieldId>
GetSizeFromFieldId(const FieldId & s)71 uint32_t GetSizeFromFieldId(const FieldId &s) {
72 return s.size;
73 }
74
75 // C2ParamField -> ParamField
76 template <typename ParamField>
objcpy(ParamField * d,const C2ParamField & s)77 bool objcpy(ParamField *d, const C2ParamField &s) {
78 d->index = static_cast<decltype(d->index)>(_C2ParamInspector::GetIndex(s));
79 SetFieldId(
80 &d->fieldId,
81 static_cast<uint32_t>(_C2ParamInspector::GetOffset(s)),
82 static_cast<uint32_t>(_C2ParamInspector::GetSize(s)));
83 return true;
84 }
85
86 template <typename ParamField>
87 struct C2ParamFieldBuilder : public C2ParamField {
C2ParamFieldBuilderC2ParamFieldBuilder88 C2ParamFieldBuilder() : C2ParamField(
89 static_cast<C2Param::Index>(static_cast<uint32_t>(0)), 0, 0) {
90 }
91 // ParamField -> C2ParamField
C2ParamFieldBuilderC2ParamFieldBuilder92 C2ParamFieldBuilder(const ParamField& s) : C2ParamField(
93 static_cast<C2Param::Index>(static_cast<uint32_t>(s.index)),
94 static_cast<uint32_t>(GetOffsetFromFieldId(s.fieldId)),
95 static_cast<uint32_t>(GetSizeFromFieldId(s.fieldId))) {
96 }
97 };
98
99 // C2WorkOrdinalStruct -> WorkOrdinal
100 template <typename WorkOrdinal>
objcpy(WorkOrdinal * d,const C2WorkOrdinalStruct & s)101 bool objcpy(WorkOrdinal *d, const C2WorkOrdinalStruct &s) {
102 d->frameIndex = static_cast<uint64_t>(s.frameIndex.peeku());
103 d->timestampUs = static_cast<uint64_t>(s.timestamp.peeku());
104 d->customOrdinal = static_cast<uint64_t>(s.customOrdinal.peeku());
105 return true;
106 }
107
108 // WorkOrdinal -> C2WorkOrdinalStruct
109 template <typename WorkOrdinal>
objcpy(C2WorkOrdinalStruct * d,const WorkOrdinal & s)110 bool objcpy(C2WorkOrdinalStruct *d, const WorkOrdinal &s) {
111 d->frameIndex = c2_cntr64_t(s.frameIndex);
112 d->timestamp = c2_cntr64_t(s.timestampUs);
113 d->customOrdinal = c2_cntr64_t(s.customOrdinal);
114 return true;
115 }
116
117 // C2FieldSupportedValues::range's type -> ValueRange
118 template <typename ValueRange>
objcpy(ValueRange * d,const decltype (C2FieldSupportedValues::range)& s)119 bool objcpy(
120 ValueRange* d,
121 const decltype(C2FieldSupportedValues::range)& s) {
122 d->min = static_cast<decltype(d->min)>(s.min.u64);
123 d->max = static_cast<decltype(d->max)>(s.max.u64);
124 d->step = static_cast<decltype(d->step)>(s.step.u64);
125 d->num = static_cast<decltype(d->num)>(s.num.u64);
126 d->denom = static_cast<decltype(d->denom)>(s.denom.u64);
127 return true;
128 }
129
130 // ValueRange -> C2FieldSupportedValues::range's type
131 template <typename ValueRange>
objcpy(decltype (C2FieldSupportedValues::range)* d,const ValueRange & s)132 bool objcpy(
133 decltype(C2FieldSupportedValues::range)* d,
134 const ValueRange& s) {
135 d->min.u64 = static_cast<uint64_t>(s.min);
136 d->max.u64 = static_cast<uint64_t>(s.max);
137 d->step.u64 = static_cast<uint64_t>(s.step);
138 d->num.u64 = static_cast<uint64_t>(s.num);
139 d->denom.u64 = static_cast<uint64_t>(s.denom);
140 return true;
141 }
142
143 template <typename Status>
SetStatus(Status * dst,c2_status_t src)144 void SetStatus(Status *dst, c2_status_t src) {
145 *dst = static_cast<Status>(src);
146 }
147
148 template <typename Status>
GetStatus(const Status & status)149 c2_status_t GetStatus(const Status &status) {
150 return static_cast<c2_status_t>(status);
151 }
152
153 // C2FieldSupportedValues -> FieldSupportedValues
154 template <typename FieldSupportedValues>
155 bool objcpy(FieldSupportedValues *d, const C2FieldSupportedValues &s);
156
157 // FieldSupportedValues -> C2FieldSupportedValues
158 template <typename FieldSupportedValues>
159 bool objcpy(C2FieldSupportedValues *d, const FieldSupportedValues &s);
160
161 // C2FieldSupportedValuesQuery -> FieldSupportedValuesQuery, FieldSupportedValuesQueryResult
162 template <typename FieldSupportedValuesQueryPtr>
objcpy(FieldSupportedValuesQueryPtr dq,nullptr_t,const C2FieldSupportedValuesQuery & s)163 bool objcpy(
164 FieldSupportedValuesQueryPtr dq,
165 nullptr_t,
166 const C2FieldSupportedValuesQuery& s) {
167 static_assert(!std::is_null_pointer_v<FieldSupportedValuesQueryPtr>);
168 static_assert(std::is_pointer_v<FieldSupportedValuesQueryPtr>);
169 typedef std::remove_pointer_t<FieldSupportedValuesQueryPtr> FieldSupportedValuesQuery;
170 if (!dq) {
171 return false;
172 }
173 if (!objcpy(&dq->field, s.field())) {
174 LOG(ERROR) << "Invalid C2FieldSupportedValuesQuery::field.";
175 return false;
176 }
177 switch (s.type()) {
178 case C2FieldSupportedValuesQuery::POSSIBLE:
179 dq->type = FieldSupportedValuesQuery::Type::POSSIBLE;
180 break;
181 case C2FieldSupportedValuesQuery::CURRENT:
182 dq->type = FieldSupportedValuesQuery::Type::CURRENT;
183 break;
184 default:
185 LOG(DEBUG) << "Unrecognized C2FieldSupportedValuesQuery::type_t "
186 << "with underlying value " << underlying_value(s.type())
187 << ".";
188 dq->type = static_cast<decltype(dq->type)>(s.type());
189 }
190 return true;
191 }
192
193 template <typename FieldSupportedValuesQueryResultPtr>
objcpy(nullptr_t,FieldSupportedValuesQueryResultPtr dr,const C2FieldSupportedValuesQuery & s)194 bool objcpy(
195 nullptr_t,
196 FieldSupportedValuesQueryResultPtr dr,
197 const C2FieldSupportedValuesQuery& s) {
198 static_assert(!std::is_null_pointer_v<FieldSupportedValuesQueryResultPtr>);
199 static_assert(std::is_pointer_v<FieldSupportedValuesQueryResultPtr>);
200 if (!dr) {
201 return false;
202 }
203 SetStatus(&dr->status, s.status);
204 return objcpy(&dr->values, s.values);
205 }
206
207 template <typename FieldSupportedValuesQueryPtr, typename FieldSupportedValuesQueryResultPtr>
objcpy(FieldSupportedValuesQueryPtr dq,FieldSupportedValuesQueryResultPtr dr,const C2FieldSupportedValuesQuery & s)208 bool objcpy(
209 FieldSupportedValuesQueryPtr dq,
210 FieldSupportedValuesQueryResultPtr dr,
211 const C2FieldSupportedValuesQuery& s) {
212 if (!objcpy(dq, nullptr, s)) {
213 return false;
214 }
215 return objcpy(nullptr, dr, s);
216 }
217
218 // FieldSupportedValuesQuery -> C2FieldSupportedValuesQuery
219 template <typename FieldSupportedValuesQuery>
objcpy(C2FieldSupportedValuesQuery * d,const FieldSupportedValuesQuery & s)220 bool objcpy(
221 C2FieldSupportedValuesQuery* d,
222 const FieldSupportedValuesQuery& s) {
223 C2FieldSupportedValuesQuery::type_t dType;
224 switch (s.type) {
225 case FieldSupportedValuesQuery::Type::POSSIBLE:
226 dType = C2FieldSupportedValuesQuery::POSSIBLE;
227 break;
228 case FieldSupportedValuesQuery::Type::CURRENT:
229 dType = C2FieldSupportedValuesQuery::CURRENT;
230 break;
231 default:
232 LOG(DEBUG) << "Unrecognized FieldSupportedValuesQuery::Type "
233 << "with underlying value " << underlying_value(s.type)
234 << ".";
235 dType = static_cast<C2FieldSupportedValuesQuery::type_t>(s.type);
236 }
237 *d = C2FieldSupportedValuesQuery(C2ParamFieldBuilder(s.field), dType);
238 return true;
239 }
240
241 // FieldSupportedValuesQuery, FieldSupportedValuesQueryResult ->
242 // C2FieldSupportedValuesQuery
243 template <typename FieldSupportedValuesQuery,
244 typename FieldSupportedValuesQueryResult>
objcpy(C2FieldSupportedValuesQuery * d,const FieldSupportedValuesQuery & sq,const FieldSupportedValuesQueryResult & sr)245 bool objcpy(
246 C2FieldSupportedValuesQuery* d,
247 const FieldSupportedValuesQuery& sq,
248 const FieldSupportedValuesQueryResult& sr) {
249 if (!objcpy(d, sq)) {
250 LOG(ERROR) << "Invalid FieldSupportedValuesQuery.";
251 return false;
252 }
253 d->status = GetStatus(sr.status);
254 if (!objcpy(&d->values, sr.values)) {
255 LOG(ERROR) << "Invalid FieldSupportedValuesQueryResult::values.";
256 return false;
257 }
258 return true;
259 }
260
261 // C2Component::Traits -> IComponentStore::ComponentTraits
262 template <typename ComponentTraits>
objcpy(ComponentTraits * d,const C2Component::Traits & s)263 bool objcpy(
264 ComponentTraits *d,
265 const C2Component::Traits &s) {
266 d->name = s.name;
267
268 switch (s.domain) {
269 case C2Component::DOMAIN_VIDEO:
270 d->domain = ComponentTraits::Domain::VIDEO;
271 break;
272 case C2Component::DOMAIN_AUDIO:
273 d->domain = ComponentTraits::Domain::AUDIO;
274 break;
275 case C2Component::DOMAIN_IMAGE:
276 d->domain = ComponentTraits::Domain::IMAGE;
277 break;
278 case C2Component::DOMAIN_OTHER:
279 d->domain = ComponentTraits::Domain::OTHER;
280 break;
281 default:
282 LOG(DEBUG) << "Unrecognized C2Component::domain_t "
283 << "with underlying value " << underlying_value(s.domain)
284 << ".";
285 d->domain = static_cast<decltype(d->domain)>(s.domain);
286 }
287
288 switch (s.kind) {
289 case C2Component::KIND_DECODER:
290 d->kind = ComponentTraits::Kind::DECODER;
291 break;
292 case C2Component::KIND_ENCODER:
293 d->kind = ComponentTraits::Kind::ENCODER;
294 break;
295 case C2Component::KIND_OTHER:
296 d->kind = ComponentTraits::Kind::OTHER;
297 break;
298 default:
299 LOG(DEBUG) << "Unrecognized C2Component::kind_t "
300 << "with underlying value " << underlying_value(s.kind)
301 << ".";
302 d->kind = static_cast<decltype(d->kind)>(s.kind);
303 }
304
305 d->rank = static_cast<uint32_t>(s.rank);
306
307 d->mediaType = s.mediaType;
308
309 d->aliases.resize(s.aliases.size());
310 for (size_t ix = s.aliases.size(); ix > 0; ) {
311 --ix;
312 d->aliases[ix] = s.aliases[ix];
313 }
314 return true;
315 }
316
317 // ComponentTraits -> C2Component::Traits, std::unique_ptr<std::vector<std::string>>
318 template <typename ComponentTraits>
objcpy(C2Component::Traits * d,const ComponentTraits & s)319 bool objcpy(
320 C2Component::Traits* d,
321 const ComponentTraits& s) {
322 d->name = s.name.c_str();
323
324 switch (s.domain) {
325 case ComponentTraits::Domain::VIDEO:
326 d->domain = C2Component::DOMAIN_VIDEO;
327 break;
328 case ComponentTraits::Domain::AUDIO:
329 d->domain = C2Component::DOMAIN_AUDIO;
330 break;
331 case ComponentTraits::Domain::IMAGE:
332 d->domain = C2Component::DOMAIN_IMAGE;
333 break;
334 case ComponentTraits::Domain::OTHER:
335 d->domain = C2Component::DOMAIN_OTHER;
336 break;
337 default:
338 LOG(DEBUG) << "Unrecognized ComponentTraits::Domain "
339 << "with underlying value " << underlying_value(s.domain)
340 << ".";
341 d->domain = static_cast<C2Component::domain_t>(s.domain);
342 }
343
344 switch (s.kind) {
345 case ComponentTraits::Kind::DECODER:
346 d->kind = C2Component::KIND_DECODER;
347 break;
348 case ComponentTraits::Kind::ENCODER:
349 d->kind = C2Component::KIND_ENCODER;
350 break;
351 case ComponentTraits::Kind::OTHER:
352 d->kind = C2Component::KIND_OTHER;
353 break;
354 default:
355 LOG(DEBUG) << "Unrecognized ComponentTraits::Kind "
356 << "with underlying value " << underlying_value(s.kind)
357 << ".";
358 d->kind = static_cast<C2Component::kind_t>(s.kind);
359 }
360
361 d->rank = static_cast<C2Component::rank_t>(s.rank);
362 d->mediaType = s.mediaType.c_str();
363 d->aliases.resize(s.aliases.size());
364 for (size_t i = 0; i < s.aliases.size(); ++i) {
365 d->aliases[i] = s.aliases[i];
366 }
367 return true;
368 }
369
370 // C2ParamFieldValues -> ParamFieldValues
371 template <typename ParamFieldValues>
objcpy(ParamFieldValues * d,const C2ParamFieldValues & s)372 bool objcpy(
373 ParamFieldValues *d,
374 const C2ParamFieldValues &s) {
375 if (!objcpy(&d->paramOrField, s.paramOrField)) {
376 LOG(ERROR) << "Invalid C2ParamFieldValues::paramOrField.";
377 return false;
378 }
379 if (s.values) {
380 d->values.resize(1);
381 if (!objcpy(&d->values[0], *s.values)) {
382 LOG(ERROR) << "Invalid C2ParamFieldValues::values.";
383 return false;
384 }
385 return true;
386 }
387 d->values.resize(0);
388 return true;
389 }
390
391 // ParamFieldValues -> C2ParamFieldValues
392 template <typename ParamFieldValues>
objcpy(C2ParamFieldValues * d,const ParamFieldValues & s)393 bool objcpy(
394 C2ParamFieldValues *d,
395 const ParamFieldValues &s) {
396 d->paramOrField = C2ParamFieldBuilder(s.paramOrField);
397 if (s.values.size() == 1) {
398 d->values = std::make_unique<C2FieldSupportedValues>();
399 if (!objcpy(d->values.get(), s.values[0])) {
400 LOG(ERROR) << "Invalid ParamFieldValues::values.";
401 return false;
402 }
403 return true;
404 } else if (s.values.size() == 0) {
405 d->values.reset();
406 return true;
407 }
408 LOG(ERROR) << "Invalid ParamFieldValues: "
409 "Two or more FieldSupportedValues objects exist in "
410 "ParamFieldValues. "
411 "Only zero or one is allowed.";
412 return false;
413 }
414
415 // C2SettingResult -> SettingResult
416 template <typename SettingResult>
objcpy(SettingResult * d,const C2SettingResult & s)417 bool objcpy(
418 SettingResult *d,
419 const C2SettingResult &s) {
420 switch (s.failure) {
421 case C2SettingResult::BAD_TYPE:
422 d->failure = SettingResult::Failure::BAD_TYPE;
423 break;
424 case C2SettingResult::BAD_PORT:
425 d->failure = SettingResult::Failure::BAD_PORT;
426 break;
427 case C2SettingResult::BAD_INDEX:
428 d->failure = SettingResult::Failure::BAD_INDEX;
429 break;
430 case C2SettingResult::READ_ONLY:
431 d->failure = SettingResult::Failure::READ_ONLY;
432 break;
433 case C2SettingResult::MISMATCH:
434 d->failure = SettingResult::Failure::MISMATCH;
435 break;
436 case C2SettingResult::BAD_VALUE:
437 d->failure = SettingResult::Failure::BAD_VALUE;
438 break;
439 case C2SettingResult::CONFLICT:
440 d->failure = SettingResult::Failure::CONFLICT;
441 break;
442 case C2SettingResult::UNSUPPORTED:
443 d->failure = SettingResult::Failure::UNSUPPORTED;
444 break;
445 case C2SettingResult::INFO_BAD_VALUE:
446 d->failure = SettingResult::Failure::INFO_BAD_VALUE;
447 break;
448 case C2SettingResult::INFO_CONFLICT:
449 d->failure = SettingResult::Failure::INFO_CONFLICT;
450 break;
451 default:
452 LOG(DEBUG) << "Unrecognized C2SettingResult::Failure "
453 << "with underlying value " << underlying_value(s.failure)
454 << ".";
455 d->failure = static_cast<decltype(d->failure)>(s.failure);
456 }
457 if (!objcpy(&d->field, s.field)) {
458 LOG(ERROR) << "Invalid C2SettingResult::field.";
459 return false;
460 }
461 d->conflicts.resize(s.conflicts.size());
462 size_t i = 0;
463 for (const C2ParamFieldValues& sConflict : s.conflicts) {
464 auto &dConflict = d->conflicts[i++];
465 if (!objcpy(&dConflict, sConflict)) {
466 LOG(ERROR) << "Invalid C2SettingResult::conflicts["
467 << i - 1 << "].";
468 return false;
469 }
470 }
471 return true;
472 }
473
474 // SettingResult -> std::unique_ptr<C2SettingResult>
475 template <typename SettingResult>
objcpy(std::unique_ptr<C2SettingResult> * d,const SettingResult & s)476 bool objcpy(
477 std::unique_ptr<C2SettingResult> *d,
478 const SettingResult &s) {
479 typedef decltype((*d)->field) ParamField;
480 *d = std::unique_ptr<C2SettingResult>(new C2SettingResult {
481 .field = C2ParamFieldValues(C2ParamFieldBuilder<ParamField>()) });
482 if (!*d) {
483 LOG(ERROR) << "No memory for C2SettingResult.";
484 return false;
485 }
486
487 // failure
488 switch (s.failure) {
489 case SettingResult::Failure::BAD_TYPE:
490 (*d)->failure = C2SettingResult::BAD_TYPE;
491 break;
492 case SettingResult::Failure::BAD_PORT:
493 (*d)->failure = C2SettingResult::BAD_PORT;
494 break;
495 case SettingResult::Failure::BAD_INDEX:
496 (*d)->failure = C2SettingResult::BAD_INDEX;
497 break;
498 case SettingResult::Failure::READ_ONLY:
499 (*d)->failure = C2SettingResult::READ_ONLY;
500 break;
501 case SettingResult::Failure::MISMATCH:
502 (*d)->failure = C2SettingResult::MISMATCH;
503 break;
504 case SettingResult::Failure::BAD_VALUE:
505 (*d)->failure = C2SettingResult::BAD_VALUE;
506 break;
507 case SettingResult::Failure::CONFLICT:
508 (*d)->failure = C2SettingResult::CONFLICT;
509 break;
510 case SettingResult::Failure::UNSUPPORTED:
511 (*d)->failure = C2SettingResult::UNSUPPORTED;
512 break;
513 case SettingResult::Failure::INFO_BAD_VALUE:
514 (*d)->failure = C2SettingResult::INFO_BAD_VALUE;
515 break;
516 case SettingResult::Failure::INFO_CONFLICT:
517 (*d)->failure = C2SettingResult::INFO_CONFLICT;
518 break;
519 default:
520 LOG(DEBUG) << "Unrecognized SettingResult::Failure "
521 << "with underlying value " << underlying_value(s.failure)
522 << ".";
523 (*d)->failure = static_cast<C2SettingResult::Failure>(s.failure);
524 }
525
526 // field
527 if (!objcpy(&(*d)->field, s.field)) {
528 LOG(ERROR) << "Invalid SettingResult::field.";
529 return false;
530 }
531
532 // conflicts
533 (*d)->conflicts.clear();
534 (*d)->conflicts.reserve(s.conflicts.size());
535 for (const auto& sConflict : s.conflicts) {
536 (*d)->conflicts.emplace_back(
537 C2ParamFieldValues{ C2ParamFieldBuilder<ParamField>(), nullptr });
538 if (!objcpy(&(*d)->conflicts.back(), sConflict)) {
539 LOG(ERROR) << "Invalid SettingResult::conflicts.";
540 return false;
541 }
542 }
543 return true;
544 }
545
546 // C2ParamDescriptor -> ParamDescriptor
547 template <typename ParamDescriptor>
objcpy(ParamDescriptor * d,const C2ParamDescriptor & s)548 bool objcpy(ParamDescriptor *d, const C2ParamDescriptor &s) {
549 d->index = static_cast<decltype(d->index)>(s.index());
550 d->attrib = static_cast<decltype(d->attrib)>(
551 _C2ParamInspector::GetAttrib(s));
552 d->name = s.name();
553 copyVector<uint32_t>(&d->dependencies, s.dependencies());
554 return true;
555 }
556
557 // ParamDescriptor -> C2ParamDescriptor
558 template <typename ParamDescriptor>
objcpy(std::shared_ptr<C2ParamDescriptor> * d,const ParamDescriptor & s)559 bool objcpy(std::shared_ptr<C2ParamDescriptor> *d, const ParamDescriptor &s) {
560 std::vector<C2Param::Index> dDependencies;
561 dDependencies.reserve(s.dependencies.size());
562 for (const auto& sDependency : s.dependencies) {
563 dDependencies.emplace_back(static_cast<uint32_t>(sDependency));
564 }
565 *d = std::make_shared<C2ParamDescriptor>(
566 C2Param::Index(static_cast<uint32_t>(s.index)),
567 static_cast<C2ParamDescriptor::attrib_t>(s.attrib),
568 C2String(s.name.c_str()),
569 std::move(dDependencies));
570 return true;
571 }
572
573 // C2StructDescriptor -> StructDescriptor
574 template <typename StructDescriptor>
objcpy(StructDescriptor * d,const C2StructDescriptor & s)575 bool objcpy(StructDescriptor *d, const C2StructDescriptor &s) {
576 d->type = static_cast<decltype(d->type)>(s.coreIndex().coreIndex());
577 d->fields.resize(s.numFields());
578 size_t i = 0;
579 for (const C2FieldDescriptor& sField : s) {
580 auto& dField = d->fields[i++];
581 SetFieldId(
582 &dField.fieldId,
583 _C2ParamInspector::GetOffset(sField),
584 _C2ParamInspector::GetSize(sField));
585 dField.type = static_cast<decltype(dField.type)>(sField.type());
586 dField.extent = static_cast<uint32_t>(sField.extent());
587 dField.name = static_cast<decltype(dField.name)>(sField.name());
588 const auto& sNamedValues = sField.namedValues();
589 dField.namedValues.resize(sNamedValues.size());
590 size_t j = 0;
591 for (const auto& sNamedValue : sNamedValues) {
592 auto& dNamedValue = dField.namedValues[j++];
593 dNamedValue.name = static_cast<decltype(dNamedValue.name)>(sNamedValue.first);
594 dNamedValue.value = static_cast<decltype(dNamedValue.value)>(
595 sNamedValue.second.u64);
596 }
597 }
598 return true;
599 }
600
601 // StructDescriptor -> C2StructDescriptor
602 template <typename StructDescriptor>
objcpy(std::unique_ptr<C2StructDescriptor> * d,const StructDescriptor & s)603 bool objcpy(std::unique_ptr<C2StructDescriptor> *d, const StructDescriptor &s) {
604 C2Param::CoreIndex dIndex = C2Param::CoreIndex(static_cast<uint32_t>(s.type));
605 std::vector<C2FieldDescriptor> dFields;
606 dFields.reserve(s.fields.size());
607 for (const auto &sField : s.fields) {
608 C2FieldDescriptor dField = {
609 static_cast<uint32_t>(sField.type),
610 static_cast<uint32_t>(sField.extent),
611 sField.name,
612 GetOffsetFromFieldId(sField.fieldId),
613 GetSizeFromFieldId(sField.fieldId) };
614 C2FieldDescriptor::NamedValuesType namedValues;
615 namedValues.reserve(sField.namedValues.size());
616 for (const auto& sNamedValue : sField.namedValues) {
617 namedValues.emplace_back(
618 sNamedValue.name,
619 C2Value::Primitive(static_cast<uint64_t>(sNamedValue.value)));
620 }
621 _C2ParamInspector::AddNamedValues(dField, std::move(namedValues));
622 dFields.emplace_back(dField);
623 }
624 *d = std::make_unique<C2StructDescriptor>(
625 _C2ParamInspector::CreateStructDescriptor(dIndex, std::move(dFields)));
626 return true;
627 }
628
629 constexpr size_t PARAMS_ALIGNMENT = 8; // 64-bit alignment
630 static_assert(PARAMS_ALIGNMENT % alignof(C2Param) == 0, "C2Param alignment mismatch");
631 static_assert(PARAMS_ALIGNMENT % alignof(C2Info) == 0, "C2Param alignment mismatch");
632 static_assert(PARAMS_ALIGNMENT % alignof(C2Tuning) == 0, "C2Param alignment mismatch");
633
634 template <typename Params>
635 struct _ParamsBlobHelper { typedef Params BlobType; };
636
637 template <typename Params>
638 using ParamsBlobType = typename _ParamsBlobHelper<Params>::BlobType;
639
640 template <typename Params>
GetBlob(const Params & params)641 const ParamsBlobType<Params> &GetBlob(const Params ¶ms) {
642 return params;
643 }
644
645 template <typename Params>
GetBlob(Params * params)646 ParamsBlobType<Params> *GetBlob(Params *params) {
647 return params;
648 }
649
650 // Params -> std::vector<C2Param*>
651 template <typename Params>
parseParamsBlob(std::vector<C2Param * > * params,const Params & paramsBlob)652 bool parseParamsBlob(std::vector<C2Param*> *params, const Params ¶msBlob) {
653 // assuming blob is const here
654 const ParamsBlobType<Params> &blob = GetBlob(paramsBlob);
655 size_t size = blob.size();
656 size_t ix = 0;
657 size_t old_ix = 0;
658 const uint8_t *data = blob.data();
659 C2Param *p = nullptr;
660
661 do {
662 p = C2ParamUtils::ParseFirst(data + ix, size - ix);
663 if (p) {
664 params->emplace_back(p);
665 old_ix = ix;
666 ix += p->size();
667 ix = align(ix, PARAMS_ALIGNMENT);
668 if (ix <= old_ix || ix > size) {
669 android_errorWriteLog(0x534e4554, "238083570");
670 break;
671 }
672 }
673 } while (p);
674
675 if (ix != size) {
676 LOG(ERROR) << "parseParamsBlob -- inconsistent sizes.";
677 return false;
678 }
679 return true;
680 }
681
682 /**
683 * Concatenates a list of C2Params into a params blob. T is a container type
684 * whose member type is compatible with C2Param*.
685 *
686 * \param[out] blob target blob
687 * \param[in] params parameters to concatenate
688 * \retval C2_OK if the blob was successfully created
689 * \retval C2_BAD_VALUE if the blob was not successful created (this only
690 * happens if the parameters were not const)
691 */
692 template <typename Params, typename T>
_createParamsBlob(Params * paramsBlob,const T & params)693 bool _createParamsBlob(Params *paramsBlob, const T ¶ms) {
694 // assuming the parameter values are const
695 size_t size = 0;
696 for (const auto &p : params) {
697 if (!p) {
698 continue;
699 }
700 size += p->size();
701 size = align(size, PARAMS_ALIGNMENT);
702 }
703 ParamsBlobType<Params> *blob = GetBlob(paramsBlob);
704 blob->resize(size);
705 size_t ix = 0;
706 for (const auto &p : params) {
707 if (!p) {
708 continue;
709 }
710 // NEVER overwrite even if param values (e.g. size) changed
711 size_t paramSize = std::min(p->size(), size - ix);
712 std::copy(
713 reinterpret_cast<const uint8_t*>(&*p),
714 reinterpret_cast<const uint8_t*>(&*p) + paramSize,
715 &(*blob)[ix]);
716 ix += paramSize;
717 ix = align(ix, PARAMS_ALIGNMENT);
718 }
719 blob->resize(ix);
720 if (ix != size) {
721 LOG(ERROR) << "createParamsBlob -- inconsistent sizes.";
722 return false;
723 }
724 return true;
725 }
726
727 /**
728 * Parses a params blob and create a vector of new T objects that contain copies
729 * of the params in the blob. T is C2Param or its compatible derived class.
730 *
731 * \param[out] params the resulting vector
732 * \param[in] blob parameter blob to parse
733 * \retval C2_OK if the full blob was parsed and params was constructed
734 * \retval C2_BAD_VALUE otherwise
735 */
736 template <typename Params, typename T>
_copyParamsFromBlob(std::vector<std::unique_ptr<T>> * params,const Params & paramsBlob)737 bool _copyParamsFromBlob(
738 std::vector<std::unique_ptr<T>>* params,
739 const Params ¶msBlob) {
740 const ParamsBlobType<Params> &blob = GetBlob(paramsBlob);
741 std::vector<C2Param*> paramPointers;
742 if (!parseParamsBlob(¶mPointers, blob)) {
743 LOG(ERROR) << "copyParamsFromBlob -- failed to parse.";
744 return false;
745 }
746
747 params->resize(paramPointers.size());
748 size_t i = 0;
749 for (C2Param* const& paramPointer : paramPointers) {
750 if (!paramPointer) {
751 LOG(ERROR) << "copyParamsFromBlob -- null paramPointer.";
752 return false;
753 }
754 (*params)[i++].reset(reinterpret_cast<T*>(
755 C2Param::Copy(*paramPointer).release()));
756 }
757 return true;
758 }
759
760 // Params -> update std::vector<std::unique_ptr<C2Param>>
761 template <typename Params>
updateParamsFromBlob(const std::vector<C2Param * > & params,const Params & paramsBlob)762 bool updateParamsFromBlob(
763 const std::vector<C2Param*>& params,
764 const Params& paramsBlob) {
765 const ParamsBlobType<Params> &blob = GetBlob(paramsBlob);
766 std::unordered_map<uint32_t, C2Param*> index2param;
767 for (C2Param* const& param : params) {
768 if (!param) {
769 LOG(ERROR) << "updateParamsFromBlob -- null output param.";
770 return false;
771 }
772 if (index2param.find(param->index()) == index2param.end()) {
773 index2param.emplace(param->index(), param);
774 }
775 }
776
777 std::vector<C2Param*> paramPointers;
778 if (!parseParamsBlob(¶mPointers, blob)) {
779 LOG(ERROR) << "updateParamsFromBlob -- failed to parse.";
780 return false;
781 }
782
783 for (C2Param* const& paramPointer : paramPointers) {
784 if (!paramPointer) {
785 LOG(ERROR) << "updateParamsFromBlob -- null input param.";
786 return false;
787 }
788 decltype(index2param)::iterator i = index2param.find(
789 paramPointer->index());
790 if (i == index2param.end()) {
791 LOG(DEBUG) << "updateParamsFromBlob -- index "
792 << paramPointer->index() << " not found. Skipping...";
793 continue;
794 }
795 if (!i->second->updateFrom(*paramPointer)) {
796 LOG(ERROR) << "updateParamsFromBlob -- size mismatch: "
797 << params.size() << " vs " << paramPointer->size()
798 << " (index = " << i->first << ").";
799 return false;
800 }
801 }
802 return true;
803 }
804
805 } // namespace android
806
807 #endif // CODEC2_COMMON_PARAM_TYPES_H
808