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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "Codec2-types"
19 #include <android-base/logging.h>
20
21 #include <codec2/hidl/1.0/types.h>
22 #include <media/stagefright/foundation/AUtils.h>
23
24 #include <C2AllocatorIon.h>
25 #include <C2AllocatorGralloc.h>
26 #include <C2BlockInternal.h>
27 #include <C2Buffer.h>
28 #include <C2Component.h>
29 #include <C2Param.h>
30 #include <C2ParamInternal.h>
31 #include <C2PlatformSupport.h>
32 #include <C2Work.h>
33 #include <util/C2ParamUtils.h>
34
35 #include <algorithm>
36 #include <functional>
37 #include <iomanip>
38 #include <unordered_map>
39
40 namespace android {
41 namespace hardware {
42 namespace media {
43 namespace c2 {
44 namespace V1_0 {
45 namespace utils {
46
47 using ::android::hardware::Return;
48 using ::android::hardware::media::bufferpool::BufferPoolData;
49 using ::android::hardware::media::bufferpool::V2_0::BufferStatusMessage;
50 using ::android::hardware::media::bufferpool::V2_0::ResultStatus;
51 using ::android::hardware::media::bufferpool::V2_0::implementation::
52 ClientManager;
53 using ::android::hardware::media::bufferpool::V2_0::implementation::
54 TransactionId;
55
asString(Status status,const char * def)56 const char* asString(Status status, const char* def) {
57 return asString(static_cast<c2_status_t>(status), def);
58 }
59
60 namespace /* unnamed */ {
61
62 template <typename EnumClass>
underlying_value(EnumClass x)63 typename std::underlying_type<EnumClass>::type underlying_value(
64 EnumClass x) {
65 return static_cast<typename std::underlying_type<EnumClass>::type>(x);
66 }
67
68 template <typename Common, typename DstVector, typename SrcVector>
copyVector(DstVector * d,const SrcVector & s)69 void copyVector(DstVector* d, const SrcVector& s) {
70 static_assert(sizeof(Common) == sizeof(decltype((*d)[0])),
71 "DstVector's component size does not match Common");
72 static_assert(sizeof(Common) == sizeof(decltype(s[0])),
73 "SrcVector's component size does not match Common");
74 d->resize(s.size());
75 std::copy(
76 reinterpret_cast<const Common*>(&s[0]),
77 reinterpret_cast<const Common*>(&s[0] + s.size()),
78 reinterpret_cast<Common*>(&(*d)[0]));
79 }
80
81 // C2ParamField -> ParamField
objcpy(ParamField * d,const C2ParamField & s)82 bool objcpy(ParamField *d, const C2ParamField &s) {
83 d->index = static_cast<ParamIndex>(_C2ParamInspector::GetIndex(s));
84 d->fieldId.offset = static_cast<uint32_t>(_C2ParamInspector::GetOffset(s));
85 d->fieldId.size = static_cast<uint32_t>(_C2ParamInspector::GetSize(s));
86 return true;
87 }
88
89 struct C2ParamFieldBuilder : public C2ParamField {
C2ParamFieldBuilderandroid::hardware::media::c2::V1_0::utils::__anon652206de0111::C2ParamFieldBuilder90 C2ParamFieldBuilder() : C2ParamField(
91 static_cast<C2Param::Index>(static_cast<uint32_t>(0)), 0, 0) {
92 }
93 // ParamField -> C2ParamField
C2ParamFieldBuilderandroid::hardware::media::c2::V1_0::utils::__anon652206de0111::C2ParamFieldBuilder94 C2ParamFieldBuilder(const ParamField& s) : C2ParamField(
95 static_cast<C2Param::Index>(static_cast<uint32_t>(s.index)),
96 static_cast<uint32_t>(s.fieldId.offset),
97 static_cast<uint32_t>(s.fieldId.size)) {
98 }
99 };
100
101 // C2WorkOrdinalStruct -> WorkOrdinal
objcpy(WorkOrdinal * d,const C2WorkOrdinalStruct & s)102 bool objcpy(WorkOrdinal *d, const C2WorkOrdinalStruct &s) {
103 d->frameIndex = static_cast<uint64_t>(s.frameIndex.peeku());
104 d->timestampUs = static_cast<uint64_t>(s.timestamp.peeku());
105 d->customOrdinal = static_cast<uint64_t>(s.customOrdinal.peeku());
106 return true;
107 }
108
109 // WorkOrdinal -> C2WorkOrdinalStruct
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
objcpy(ValueRange * d,const decltype(C2FieldSupportedValues::range) & s)118 bool objcpy(
119 ValueRange* d,
120 const decltype(C2FieldSupportedValues::range)& s) {
121 d->min = static_cast<PrimitiveValue>(s.min.u64);
122 d->max = static_cast<PrimitiveValue>(s.max.u64);
123 d->step = static_cast<PrimitiveValue>(s.step.u64);
124 d->num = static_cast<PrimitiveValue>(s.num.u64);
125 d->denom = static_cast<PrimitiveValue>(s.denom.u64);
126 return true;
127 }
128
129 // C2FieldSupportedValues -> FieldSupportedValues
objcpy(FieldSupportedValues * d,const C2FieldSupportedValues & s)130 bool objcpy(FieldSupportedValues *d, const C2FieldSupportedValues &s) {
131 switch (s.type) {
132 case C2FieldSupportedValues::EMPTY: {
133 d->empty(::android::hidl::safe_union::V1_0::Monostate{});
134 break;
135 }
136 case C2FieldSupportedValues::RANGE: {
137 ValueRange range{};
138 if (!objcpy(&range, s.range)) {
139 LOG(ERROR) << "Invalid C2FieldSupportedValues::range.";
140 d->range(range);
141 return false;
142 }
143 d->range(range);
144 break;
145 }
146 case C2FieldSupportedValues::VALUES: {
147 hidl_vec<PrimitiveValue> values;
148 copyVector<uint64_t>(&values, s.values);
149 d->values(values);
150 break;
151 }
152 case C2FieldSupportedValues::FLAGS: {
153 hidl_vec<PrimitiveValue> flags;
154 copyVector<uint64_t>(&flags, s.values);
155 d->flags(flags);
156 break;
157 }
158 default:
159 LOG(DEBUG) << "Unrecognized C2FieldSupportedValues::type_t "
160 << "with underlying value " << underlying_value(s.type)
161 << ".";
162 return false;
163 }
164 return true;
165 }
166
167 // ValueRange -> C2FieldSupportedValues::range's type
objcpy(decltype(C2FieldSupportedValues::range) * d,const ValueRange & s)168 bool objcpy(
169 decltype(C2FieldSupportedValues::range)* d,
170 const ValueRange& s) {
171 d->min.u64 = static_cast<uint64_t>(s.min);
172 d->max.u64 = static_cast<uint64_t>(s.max);
173 d->step.u64 = static_cast<uint64_t>(s.step);
174 d->num.u64 = static_cast<uint64_t>(s.num);
175 d->denom.u64 = static_cast<uint64_t>(s.denom);
176 return true;
177 }
178
179 // FieldSupportedValues -> C2FieldSupportedValues
objcpy(C2FieldSupportedValues * d,const FieldSupportedValues & s)180 bool objcpy(C2FieldSupportedValues *d, const FieldSupportedValues &s) {
181 switch (s.getDiscriminator()) {
182 case FieldSupportedValues::hidl_discriminator::empty: {
183 d->type = C2FieldSupportedValues::EMPTY;
184 break;
185 }
186 case FieldSupportedValues::hidl_discriminator::range: {
187 d->type = C2FieldSupportedValues::RANGE;
188 if (!objcpy(&d->range, s.range())) {
189 LOG(ERROR) << "Invalid FieldSupportedValues::range.";
190 return false;
191 }
192 d->values.resize(0);
193 break;
194 }
195 case FieldSupportedValues::hidl_discriminator::values: {
196 d->type = C2FieldSupportedValues::VALUES;
197 copyVector<uint64_t>(&d->values, s.values());
198 break;
199 }
200 case FieldSupportedValues::hidl_discriminator::flags: {
201 d->type = C2FieldSupportedValues::FLAGS;
202 copyVector<uint64_t>(&d->values, s.flags());
203 break;
204 }
205 default:
206 LOG(WARNING) << "Unrecognized FieldSupportedValues::getDiscriminator()";
207 return false;
208 }
209 return true;
210 }
211
212 } // unnamed namespace
213
214 // C2FieldSupportedValuesQuery -> FieldSupportedValuesQuery
objcpy(FieldSupportedValuesQuery * d,const C2FieldSupportedValuesQuery & s)215 bool objcpy(
216 FieldSupportedValuesQuery* d,
217 const C2FieldSupportedValuesQuery& s) {
218 if (!objcpy(&d->field, s.field())) {
219 LOG(ERROR) << "Invalid C2FieldSupportedValuesQuery::field.";
220 return false;
221 }
222 switch (s.type()) {
223 case C2FieldSupportedValuesQuery::POSSIBLE:
224 d->type = FieldSupportedValuesQuery::Type::POSSIBLE;
225 break;
226 case C2FieldSupportedValuesQuery::CURRENT:
227 d->type = FieldSupportedValuesQuery::Type::CURRENT;
228 break;
229 default:
230 LOG(DEBUG) << "Unrecognized C2FieldSupportedValuesQuery::type_t "
231 << "with underlying value " << underlying_value(s.type())
232 << ".";
233 d->type = static_cast<FieldSupportedValuesQuery::Type>(s.type());
234 }
235 return true;
236 }
237
238 // FieldSupportedValuesQuery -> C2FieldSupportedValuesQuery
objcpy(C2FieldSupportedValuesQuery * d,const FieldSupportedValuesQuery & s)239 bool objcpy(
240 C2FieldSupportedValuesQuery* d,
241 const FieldSupportedValuesQuery& s) {
242 C2FieldSupportedValuesQuery::type_t dType;
243 switch (s.type) {
244 case FieldSupportedValuesQuery::Type::POSSIBLE:
245 dType = C2FieldSupportedValuesQuery::POSSIBLE;
246 break;
247 case FieldSupportedValuesQuery::Type::CURRENT:
248 dType = C2FieldSupportedValuesQuery::CURRENT;
249 break;
250 default:
251 LOG(DEBUG) << "Unrecognized FieldSupportedValuesQuery::Type "
252 << "with underlying value " << underlying_value(s.type)
253 << ".";
254 dType = static_cast<C2FieldSupportedValuesQuery::type_t>(s.type);
255 }
256 *d = C2FieldSupportedValuesQuery(C2ParamFieldBuilder(s.field), dType);
257 return true;
258 }
259
260 // C2FieldSupportedValuesQuery -> FieldSupportedValuesQueryResult
objcpy(FieldSupportedValuesQueryResult * d,const C2FieldSupportedValuesQuery & s)261 bool objcpy(
262 FieldSupportedValuesQueryResult* d,
263 const C2FieldSupportedValuesQuery& s) {
264 d->status = static_cast<Status>(s.status);
265 return objcpy(&d->values, s.values);
266 }
267
268 // FieldSupportedValuesQuery, FieldSupportedValuesQueryResult ->
269 // C2FieldSupportedValuesQuery
objcpy(C2FieldSupportedValuesQuery * d,const FieldSupportedValuesQuery & sq,const FieldSupportedValuesQueryResult & sr)270 bool objcpy(
271 C2FieldSupportedValuesQuery* d,
272 const FieldSupportedValuesQuery& sq,
273 const FieldSupportedValuesQueryResult& sr) {
274 if (!objcpy(d, sq)) {
275 LOG(ERROR) << "Invalid FieldSupportedValuesQuery.";
276 return false;
277 }
278 d->status = static_cast<c2_status_t>(sr.status);
279 if (!objcpy(&d->values, sr.values)) {
280 LOG(ERROR) << "Invalid FieldSupportedValuesQueryResult::values.";
281 return false;
282 }
283 return true;
284 }
285
286 // C2Component::Traits -> IComponentStore::ComponentTraits
objcpy(IComponentStore::ComponentTraits * d,const C2Component::Traits & s)287 bool objcpy(
288 IComponentStore::ComponentTraits *d,
289 const C2Component::Traits &s) {
290 d->name = s.name;
291
292 switch (s.domain) {
293 case C2Component::DOMAIN_VIDEO:
294 d->domain = IComponentStore::ComponentTraits::Domain::VIDEO;
295 break;
296 case C2Component::DOMAIN_AUDIO:
297 d->domain = IComponentStore::ComponentTraits::Domain::AUDIO;
298 break;
299 case C2Component::DOMAIN_IMAGE:
300 d->domain = IComponentStore::ComponentTraits::Domain::IMAGE;
301 break;
302 case C2Component::DOMAIN_OTHER:
303 d->domain = IComponentStore::ComponentTraits::Domain::OTHER;
304 break;
305 default:
306 LOG(DEBUG) << "Unrecognized C2Component::domain_t "
307 << "with underlying value " << underlying_value(s.domain)
308 << ".";
309 d->domain = static_cast<IComponentStore::ComponentTraits::Domain>(
310 s.domain);
311 }
312
313 switch (s.kind) {
314 case C2Component::KIND_DECODER:
315 d->kind = IComponentStore::ComponentTraits::Kind::DECODER;
316 break;
317 case C2Component::KIND_ENCODER:
318 d->kind = IComponentStore::ComponentTraits::Kind::ENCODER;
319 break;
320 case C2Component::KIND_OTHER:
321 d->kind = IComponentStore::ComponentTraits::Kind::OTHER;
322 break;
323 default:
324 LOG(DEBUG) << "Unrecognized C2Component::kind_t "
325 << "with underlying value " << underlying_value(s.kind)
326 << ".";
327 d->kind = static_cast<IComponentStore::ComponentTraits::Kind>(
328 s.kind);
329 }
330
331 d->rank = static_cast<uint32_t>(s.rank);
332
333 d->mediaType = s.mediaType;
334
335 d->aliases.resize(s.aliases.size());
336 for (size_t ix = s.aliases.size(); ix > 0; ) {
337 --ix;
338 d->aliases[ix] = s.aliases[ix];
339 }
340 return true;
341 }
342
343 // ComponentTraits -> C2Component::Traits, std::unique_ptr<std::vector<std::string>>
objcpy(C2Component::Traits * d,const IComponentStore::ComponentTraits & s)344 bool objcpy(
345 C2Component::Traits* d,
346 const IComponentStore::ComponentTraits& s) {
347 d->name = s.name.c_str();
348
349 switch (s.domain) {
350 case IComponentStore::ComponentTraits::Domain::VIDEO:
351 d->domain = C2Component::DOMAIN_VIDEO;
352 break;
353 case IComponentStore::ComponentTraits::Domain::AUDIO:
354 d->domain = C2Component::DOMAIN_AUDIO;
355 break;
356 case IComponentStore::ComponentTraits::Domain::IMAGE:
357 d->domain = C2Component::DOMAIN_IMAGE;
358 break;
359 case IComponentStore::ComponentTraits::Domain::OTHER:
360 d->domain = C2Component::DOMAIN_OTHER;
361 break;
362 default:
363 LOG(DEBUG) << "Unrecognized ComponentTraits::Domain "
364 << "with underlying value " << underlying_value(s.domain)
365 << ".";
366 d->domain = static_cast<C2Component::domain_t>(s.domain);
367 }
368
369 switch (s.kind) {
370 case IComponentStore::ComponentTraits::Kind::DECODER:
371 d->kind = C2Component::KIND_DECODER;
372 break;
373 case IComponentStore::ComponentTraits::Kind::ENCODER:
374 d->kind = C2Component::KIND_ENCODER;
375 break;
376 case IComponentStore::ComponentTraits::Kind::OTHER:
377 d->kind = C2Component::KIND_OTHER;
378 break;
379 default:
380 LOG(DEBUG) << "Unrecognized ComponentTraits::Kind "
381 << "with underlying value " << underlying_value(s.kind)
382 << ".";
383 d->kind = static_cast<C2Component::kind_t>(s.kind);
384 }
385
386 d->rank = static_cast<C2Component::rank_t>(s.rank);
387 d->mediaType = s.mediaType.c_str();
388 d->aliases.resize(s.aliases.size());
389 for (size_t i = 0; i < s.aliases.size(); ++i) {
390 d->aliases[i] = s.aliases[i];
391 }
392 return true;
393 }
394
395 namespace /* unnamed */ {
396
397 // C2ParamFieldValues -> ParamFieldValues
objcpy(ParamFieldValues * d,const C2ParamFieldValues & s)398 bool objcpy(ParamFieldValues *d, const C2ParamFieldValues &s) {
399 if (!objcpy(&d->paramOrField, s.paramOrField)) {
400 LOG(ERROR) << "Invalid C2ParamFieldValues::paramOrField.";
401 return false;
402 }
403 if (s.values) {
404 d->values.resize(1);
405 if (!objcpy(&d->values[0], *s.values)) {
406 LOG(ERROR) << "Invalid C2ParamFieldValues::values.";
407 return false;
408 }
409 return true;
410 }
411 d->values.resize(0);
412 return true;
413 }
414
415 // ParamFieldValues -> C2ParamFieldValues
objcpy(C2ParamFieldValues * d,const ParamFieldValues & s)416 bool objcpy(C2ParamFieldValues *d, const ParamFieldValues &s) {
417 d->paramOrField = C2ParamFieldBuilder(s.paramOrField);
418 if (s.values.size() == 1) {
419 d->values = std::make_unique<C2FieldSupportedValues>();
420 if (!objcpy(d->values.get(), s.values[0])) {
421 LOG(ERROR) << "Invalid ParamFieldValues::values.";
422 return false;
423 }
424 return true;
425 } else if (s.values.size() == 0) {
426 d->values.reset();
427 return true;
428 }
429 LOG(ERROR) << "Invalid ParamFieldValues: "
430 "Two or more FieldSupportedValues objects exist in "
431 "ParamFieldValues. "
432 "Only zero or one is allowed.";
433 return false;
434 }
435
436 } // unnamed namespace
437
438 // C2SettingResult -> SettingResult
objcpy(SettingResult * d,const C2SettingResult & s)439 bool objcpy(SettingResult *d, const C2SettingResult &s) {
440 switch (s.failure) {
441 case C2SettingResult::BAD_TYPE:
442 d->failure = SettingResult::Failure::BAD_TYPE;
443 break;
444 case C2SettingResult::BAD_PORT:
445 d->failure = SettingResult::Failure::BAD_PORT;
446 break;
447 case C2SettingResult::BAD_INDEX:
448 d->failure = SettingResult::Failure::BAD_INDEX;
449 break;
450 case C2SettingResult::READ_ONLY:
451 d->failure = SettingResult::Failure::READ_ONLY;
452 break;
453 case C2SettingResult::MISMATCH:
454 d->failure = SettingResult::Failure::MISMATCH;
455 break;
456 case C2SettingResult::BAD_VALUE:
457 d->failure = SettingResult::Failure::BAD_VALUE;
458 break;
459 case C2SettingResult::CONFLICT:
460 d->failure = SettingResult::Failure::CONFLICT;
461 break;
462 case C2SettingResult::UNSUPPORTED:
463 d->failure = SettingResult::Failure::UNSUPPORTED;
464 break;
465 case C2SettingResult::INFO_BAD_VALUE:
466 d->failure = SettingResult::Failure::INFO_BAD_VALUE;
467 break;
468 case C2SettingResult::INFO_CONFLICT:
469 d->failure = SettingResult::Failure::INFO_CONFLICT;
470 break;
471 default:
472 LOG(DEBUG) << "Unrecognized C2SettingResult::Failure "
473 << "with underlying value " << underlying_value(s.failure)
474 << ".";
475 d->failure = static_cast<SettingResult::Failure>(s.failure);
476 }
477 if (!objcpy(&d->field, s.field)) {
478 LOG(ERROR) << "Invalid C2SettingResult::field.";
479 return false;
480 }
481 d->conflicts.resize(s.conflicts.size());
482 size_t i = 0;
483 for (const C2ParamFieldValues& sConflict : s.conflicts) {
484 ParamFieldValues &dConflict = d->conflicts[i++];
485 if (!objcpy(&dConflict, sConflict)) {
486 LOG(ERROR) << "Invalid C2SettingResult::conflicts["
487 << i - 1 << "].";
488 return false;
489 }
490 }
491 return true;
492 }
493
494 // SettingResult -> std::unique_ptr<C2SettingResult>
objcpy(std::unique_ptr<C2SettingResult> * d,const SettingResult & s)495 bool objcpy(std::unique_ptr<C2SettingResult> *d, const SettingResult &s) {
496 *d = std::unique_ptr<C2SettingResult>(new C2SettingResult {
497 .field = C2ParamFieldValues(C2ParamFieldBuilder()) });
498 if (!*d) {
499 LOG(ERROR) << "No memory for C2SettingResult.";
500 return false;
501 }
502
503 // failure
504 switch (s.failure) {
505 case SettingResult::Failure::BAD_TYPE:
506 (*d)->failure = C2SettingResult::BAD_TYPE;
507 break;
508 case SettingResult::Failure::BAD_PORT:
509 (*d)->failure = C2SettingResult::BAD_PORT;
510 break;
511 case SettingResult::Failure::BAD_INDEX:
512 (*d)->failure = C2SettingResult::BAD_INDEX;
513 break;
514 case SettingResult::Failure::READ_ONLY:
515 (*d)->failure = C2SettingResult::READ_ONLY;
516 break;
517 case SettingResult::Failure::MISMATCH:
518 (*d)->failure = C2SettingResult::MISMATCH;
519 break;
520 case SettingResult::Failure::BAD_VALUE:
521 (*d)->failure = C2SettingResult::BAD_VALUE;
522 break;
523 case SettingResult::Failure::CONFLICT:
524 (*d)->failure = C2SettingResult::CONFLICT;
525 break;
526 case SettingResult::Failure::UNSUPPORTED:
527 (*d)->failure = C2SettingResult::UNSUPPORTED;
528 break;
529 case SettingResult::Failure::INFO_BAD_VALUE:
530 (*d)->failure = C2SettingResult::INFO_BAD_VALUE;
531 break;
532 case SettingResult::Failure::INFO_CONFLICT:
533 (*d)->failure = C2SettingResult::INFO_CONFLICT;
534 break;
535 default:
536 LOG(DEBUG) << "Unrecognized SettingResult::Failure "
537 << "with underlying value " << underlying_value(s.failure)
538 << ".";
539 (*d)->failure = static_cast<C2SettingResult::Failure>(s.failure);
540 }
541
542 // field
543 if (!objcpy(&(*d)->field, s.field)) {
544 LOG(ERROR) << "Invalid SettingResult::field.";
545 return false;
546 }
547
548 // conflicts
549 (*d)->conflicts.clear();
550 (*d)->conflicts.reserve(s.conflicts.size());
551 for (const ParamFieldValues& sConflict : s.conflicts) {
552 (*d)->conflicts.emplace_back(
553 C2ParamFieldValues{ C2ParamFieldBuilder(), nullptr });
554 if (!objcpy(&(*d)->conflicts.back(), sConflict)) {
555 LOG(ERROR) << "Invalid SettingResult::conflicts.";
556 return false;
557 }
558 }
559 return true;
560 }
561
562 // C2ParamDescriptor -> ParamDescriptor
objcpy(ParamDescriptor * d,const C2ParamDescriptor & s)563 bool objcpy(ParamDescriptor *d, const C2ParamDescriptor &s) {
564 d->index = static_cast<ParamIndex>(s.index());
565 d->attrib = static_cast<hidl_bitfield<ParamDescriptor::Attrib>>(
566 _C2ParamInspector::GetAttrib(s));
567 d->name = s.name();
568 copyVector<uint32_t>(&d->dependencies, s.dependencies());
569 return true;
570 }
571
572 // ParamDescriptor -> C2ParamDescriptor
objcpy(std::shared_ptr<C2ParamDescriptor> * d,const ParamDescriptor & s)573 bool objcpy(std::shared_ptr<C2ParamDescriptor> *d, const ParamDescriptor &s) {
574 std::vector<C2Param::Index> dDependencies;
575 dDependencies.reserve(s.dependencies.size());
576 for (const ParamIndex& sDependency : s.dependencies) {
577 dDependencies.emplace_back(static_cast<uint32_t>(sDependency));
578 }
579 *d = std::make_shared<C2ParamDescriptor>(
580 C2Param::Index(static_cast<uint32_t>(s.index)),
581 static_cast<C2ParamDescriptor::attrib_t>(s.attrib),
582 C2String(s.name.c_str()),
583 std::move(dDependencies));
584 return true;
585 }
586
587 // C2StructDescriptor -> StructDescriptor
objcpy(StructDescriptor * d,const C2StructDescriptor & s)588 bool objcpy(StructDescriptor *d, const C2StructDescriptor &s) {
589 d->type = static_cast<ParamIndex>(s.coreIndex().coreIndex());
590 d->fields.resize(s.numFields());
591 size_t i = 0;
592 for (const auto& sField : s) {
593 FieldDescriptor& dField = d->fields[i++];
594 dField.fieldId.offset = static_cast<uint32_t>(
595 _C2ParamInspector::GetOffset(sField));
596 dField.fieldId.size = static_cast<uint32_t>(
597 _C2ParamInspector::GetSize(sField));
598 dField.type = static_cast<hidl_bitfield<FieldDescriptor::Type>>(
599 sField.type());
600 dField.extent = static_cast<uint32_t>(sField.extent());
601 dField.name = static_cast<hidl_string>(sField.name());
602 const auto& sNamedValues = sField.namedValues();
603 dField.namedValues.resize(sNamedValues.size());
604 size_t j = 0;
605 for (const auto& sNamedValue : sNamedValues) {
606 FieldDescriptor::NamedValue& dNamedValue = dField.namedValues[j++];
607 dNamedValue.name = static_cast<hidl_string>(sNamedValue.first);
608 dNamedValue.value = static_cast<PrimitiveValue>(
609 sNamedValue.second.u64);
610 }
611 }
612 return true;
613 }
614
615 // StructDescriptor -> C2StructDescriptor
objcpy(std::unique_ptr<C2StructDescriptor> * d,const StructDescriptor & s)616 bool objcpy(std::unique_ptr<C2StructDescriptor> *d, const StructDescriptor &s) {
617 C2Param::CoreIndex dIndex = C2Param::CoreIndex(static_cast<uint32_t>(s.type));
618 std::vector<C2FieldDescriptor> dFields;
619 dFields.reserve(s.fields.size());
620 for (const auto &sField : s.fields) {
621 C2FieldDescriptor dField = {
622 static_cast<uint32_t>(sField.type),
623 sField.extent,
624 sField.name,
625 sField.fieldId.offset,
626 sField.fieldId.size };
627 C2FieldDescriptor::NamedValuesType namedValues;
628 namedValues.reserve(sField.namedValues.size());
629 for (const auto& sNamedValue : sField.namedValues) {
630 namedValues.emplace_back(
631 sNamedValue.name,
632 C2Value::Primitive(static_cast<uint64_t>(sNamedValue.value)));
633 }
634 _C2ParamInspector::AddNamedValues(dField, std::move(namedValues));
635 dFields.emplace_back(dField);
636 }
637 *d = std::make_unique<C2StructDescriptor>(
638 _C2ParamInspector::CreateStructDescriptor(dIndex, std::move(dFields)));
639 return true;
640 }
641
642 namespace /* unnamed */ {
643
644 // Find or add a hidl BaseBlock object from a given C2Handle* to a list and an
645 // associated map.
646 // Note: The handle is not cloned.
_addBaseBlock(uint32_t * index,const C2Handle * handle,std::list<BaseBlock> * baseBlocks,std::map<const void *,uint32_t> * baseBlockIndices)647 bool _addBaseBlock(
648 uint32_t* index,
649 const C2Handle* handle,
650 std::list<BaseBlock>* baseBlocks,
651 std::map<const void*, uint32_t>* baseBlockIndices) {
652 if (!handle) {
653 LOG(ERROR) << "addBaseBlock called on a null C2Handle.";
654 return false;
655 }
656 auto it = baseBlockIndices->find(handle);
657 if (it != baseBlockIndices->end()) {
658 *index = it->second;
659 } else {
660 *index = baseBlocks->size();
661 baseBlockIndices->emplace(handle, *index);
662 baseBlocks->emplace_back();
663
664 BaseBlock &dBaseBlock = baseBlocks->back();
665 // This does not clone the handle.
666 dBaseBlock.nativeBlock(
667 reinterpret_cast<const native_handle_t*>(handle));
668
669 }
670 return true;
671 }
672
673 // Find or add a hidl BaseBlock object from a given BufferPoolData to a list and
674 // an associated map.
_addBaseBlock(uint32_t * index,const std::shared_ptr<BufferPoolData> bpData,BufferPoolSender * bufferPoolSender,std::list<BaseBlock> * baseBlocks,std::map<const void *,uint32_t> * baseBlockIndices)675 bool _addBaseBlock(
676 uint32_t* index,
677 const std::shared_ptr<BufferPoolData> bpData,
678 BufferPoolSender* bufferPoolSender,
679 std::list<BaseBlock>* baseBlocks,
680 std::map<const void*, uint32_t>* baseBlockIndices) {
681 if (!bpData) {
682 LOG(ERROR) << "addBaseBlock called on a null BufferPoolData.";
683 return false;
684 }
685 auto it = baseBlockIndices->find(bpData.get());
686 if (it != baseBlockIndices->end()) {
687 *index = it->second;
688 } else {
689 *index = baseBlocks->size();
690 baseBlockIndices->emplace(bpData.get(), *index);
691 baseBlocks->emplace_back();
692
693 BaseBlock &dBaseBlock = baseBlocks->back();
694
695 if (bufferPoolSender) {
696 BufferStatusMessage pooledBlock;
697 ResultStatus bpStatus = bufferPoolSender->send(
698 bpData,
699 &pooledBlock);
700
701 if (bpStatus != ResultStatus::OK) {
702 LOG(ERROR) << "Failed to send buffer with BufferPool. Error: "
703 << static_cast<int32_t>(bpStatus)
704 << ".";
705 return false;
706 }
707 dBaseBlock.pooledBlock(pooledBlock);
708 }
709 }
710 return true;
711 }
712
addBaseBlock(uint32_t * index,const C2Handle * handle,const std::shared_ptr<const _C2BlockPoolData> & blockPoolData,BufferPoolSender * bufferPoolSender,std::list<BaseBlock> * baseBlocks,std::map<const void *,uint32_t> * baseBlockIndices)713 bool addBaseBlock(
714 uint32_t* index,
715 const C2Handle* handle,
716 const std::shared_ptr<const _C2BlockPoolData>& blockPoolData,
717 BufferPoolSender* bufferPoolSender,
718 std::list<BaseBlock>* baseBlocks,
719 std::map<const void*, uint32_t>* baseBlockIndices) {
720 if (!blockPoolData) {
721 // No BufferPoolData ==> NATIVE block.
722 return _addBaseBlock(
723 index, handle,
724 baseBlocks, baseBlockIndices);
725 }
726 switch (blockPoolData->getType()) {
727 case _C2BlockPoolData::TYPE_BUFFERPOOL: {
728 // BufferPoolData
729 std::shared_ptr<BufferPoolData> bpData;
730 if (!_C2BlockFactory::GetBufferPoolData(blockPoolData, &bpData)
731 || !bpData) {
732 LOG(ERROR) << "BufferPoolData unavailable in a block.";
733 return false;
734 }
735 return _addBaseBlock(
736 index, bpData,
737 bufferPoolSender, baseBlocks, baseBlockIndices);
738 }
739 case _C2BlockPoolData::TYPE_BUFFERQUEUE:
740 uint32_t gen;
741 uint64_t bqId;
742 int32_t bqSlot;
743 // Update handle if migration happened.
744 if (_C2BlockFactory::GetBufferQueueData(
745 blockPoolData, &gen, &bqId, &bqSlot)) {
746 android::MigrateNativeCodec2GrallocHandle(
747 const_cast<native_handle_t*>(handle), gen, bqId, bqSlot);
748 }
749 return _addBaseBlock(
750 index, handle,
751 baseBlocks, baseBlockIndices);
752 default:
753 LOG(ERROR) << "Unknown C2BlockPoolData type.";
754 return false;
755 }
756 }
757
758 // C2Fence -> hidl_handle
759 // Note: File descriptors are not duplicated. The original file descriptor must
760 // not be closed before the transaction is complete.
objcpy(hidl_handle * d,const C2Fence & s)761 bool objcpy(hidl_handle* d, const C2Fence& s) {
762 (void)s; // TODO: implement s.fd()
763 int fenceFd = -1;
764 d->setTo(nullptr);
765 if (fenceFd >= 0) {
766 native_handle_t *handle = native_handle_create(1, 0);
767 if (!handle) {
768 LOG(ERROR) << "Failed to create a native handle.";
769 return false;
770 }
771 handle->data[0] = fenceFd;
772 d->setTo(handle, true /* owns */);
773 }
774 return true;
775 }
776
777 // C2ConstLinearBlock -> Block
778 // Note: Native handles are not duplicated. The original handles must not be
779 // closed before the transaction is complete.
objcpy(Block * d,const C2ConstLinearBlock & s,BufferPoolSender * bufferPoolSender,std::list<BaseBlock> * baseBlocks,std::map<const void *,uint32_t> * baseBlockIndices)780 bool objcpy(Block* d, const C2ConstLinearBlock& s,
781 BufferPoolSender* bufferPoolSender,
782 std::list<BaseBlock>* baseBlocks,
783 std::map<const void*, uint32_t>* baseBlockIndices) {
784 std::shared_ptr<const _C2BlockPoolData> bpData =
785 _C2BlockFactory::GetLinearBlockPoolData(s);
786 if (!addBaseBlock(&d->index, s.handle(), bpData,
787 bufferPoolSender, baseBlocks, baseBlockIndices)) {
788 LOG(ERROR) << "Invalid block data in C2ConstLinearBlock.";
789 return false;
790 }
791
792 // Create the metadata.
793 C2Hidl_RangeInfo dRangeInfo;
794 dRangeInfo.offset = static_cast<uint32_t>(s.offset());
795 dRangeInfo.length = static_cast<uint32_t>(s.size());
796 if (!createParamsBlob(&d->meta, std::vector<C2Param*>{ &dRangeInfo })) {
797 LOG(ERROR) << "Invalid range info in C2ConstLinearBlock.";
798 return false;
799 }
800
801 // Copy the fence
802 if (!objcpy(&d->fence, s.fence())) {
803 LOG(ERROR) << "Invalid C2ConstLinearBlock::fence.";
804 return false;
805 }
806 return true;
807 }
808
809 // C2ConstGraphicBlock -> Block
810 // Note: Native handles are not duplicated. The original handles must not be
811 // closed before the transaction is complete.
objcpy(Block * d,const C2ConstGraphicBlock & s,BufferPoolSender * bufferPoolSender,std::list<BaseBlock> * baseBlocks,std::map<const void *,uint32_t> * baseBlockIndices)812 bool objcpy(Block* d, const C2ConstGraphicBlock& s,
813 BufferPoolSender* bufferPoolSender,
814 std::list<BaseBlock>* baseBlocks,
815 std::map<const void*, uint32_t>* baseBlockIndices) {
816 std::shared_ptr<const _C2BlockPoolData> bpData =
817 _C2BlockFactory::GetGraphicBlockPoolData(s);
818 if (!addBaseBlock(&d->index, s.handle(), bpData,
819 bufferPoolSender, baseBlocks, baseBlockIndices)) {
820 LOG(ERROR) << "Invalid block data in C2ConstGraphicBlock.";
821 return false;
822 }
823
824 // Create the metadata.
825 C2Hidl_RectInfo dRectInfo;
826 C2Rect sRect = s.crop();
827 dRectInfo.left = static_cast<uint32_t>(sRect.left);
828 dRectInfo.top = static_cast<uint32_t>(sRect.top);
829 dRectInfo.width = static_cast<uint32_t>(sRect.width);
830 dRectInfo.height = static_cast<uint32_t>(sRect.height);
831 if (!createParamsBlob(&d->meta, std::vector<C2Param*>{ &dRectInfo })) {
832 LOG(ERROR) << "Invalid rect info in C2ConstGraphicBlock.";
833 return false;
834 }
835
836 // Copy the fence
837 if (!objcpy(&d->fence, s.fence())) {
838 LOG(ERROR) << "Invalid C2ConstGraphicBlock::fence.";
839 return false;
840 }
841 return true;
842 }
843
844 // C2BufferData -> Buffer
845 // This function only fills in d->blocks.
objcpy(Buffer * d,const C2BufferData & s,BufferPoolSender * bufferPoolSender,std::list<BaseBlock> * baseBlocks,std::map<const void *,uint32_t> * baseBlockIndices)846 bool objcpy(Buffer* d, const C2BufferData& s,
847 BufferPoolSender* bufferPoolSender,
848 std::list<BaseBlock>* baseBlocks,
849 std::map<const void*, uint32_t>* baseBlockIndices) {
850 d->blocks.resize(
851 s.linearBlocks().size() +
852 s.graphicBlocks().size());
853 size_t i = 0;
854 for (const C2ConstLinearBlock& linearBlock : s.linearBlocks()) {
855 Block& dBlock = d->blocks[i++];
856 if (!objcpy(
857 &dBlock, linearBlock,
858 bufferPoolSender, baseBlocks, baseBlockIndices)) {
859 LOG(ERROR) << "Invalid C2BufferData::linearBlocks. "
860 << "(Destination index = " << i - 1 << ".)";
861 return false;
862 }
863 }
864 for (const C2ConstGraphicBlock& graphicBlock : s.graphicBlocks()) {
865 Block& dBlock = d->blocks[i++];
866 if (!objcpy(
867 &dBlock, graphicBlock,
868 bufferPoolSender, baseBlocks, baseBlockIndices)) {
869 LOG(ERROR) << "Invalid C2BufferData::graphicBlocks. "
870 << "(Destination index = " << i - 1 << ".)";
871 return false;
872 }
873 }
874 return true;
875 }
876
877 // C2Buffer -> Buffer
objcpy(Buffer * d,const C2Buffer & s,BufferPoolSender * bufferPoolSender,std::list<BaseBlock> * baseBlocks,std::map<const void *,uint32_t> * baseBlockIndices)878 bool objcpy(Buffer* d, const C2Buffer& s,
879 BufferPoolSender* bufferPoolSender,
880 std::list<BaseBlock>* baseBlocks,
881 std::map<const void*, uint32_t>* baseBlockIndices) {
882 if (!createParamsBlob(&d->info, s.info())) {
883 LOG(ERROR) << "Invalid C2Buffer::info.";
884 return false;
885 }
886 if (!objcpy(d, s.data(), bufferPoolSender, baseBlocks, baseBlockIndices)) {
887 LOG(ERROR) << "Invalid C2Buffer::data.";
888 return false;
889 }
890 return true;
891 }
892
893 // C2InfoBuffer -> InfoBuffer
objcpy(InfoBuffer * d,const C2InfoBuffer & s,BufferPoolSender * bufferPoolSender,std::list<BaseBlock> * baseBlocks,std::map<const void *,uint32_t> * baseBlockIndices)894 bool objcpy(InfoBuffer* d, const C2InfoBuffer& s,
895 BufferPoolSender* bufferPoolSender,
896 std::list<BaseBlock>* baseBlocks,
897 std::map<const void*, uint32_t>* baseBlockIndices) {
898 d->index = static_cast<ParamIndex>(s.index());
899 Buffer& dBuffer = d->buffer;
900 if (!objcpy(&dBuffer, s.data(), bufferPoolSender, baseBlocks, baseBlockIndices)) {
901 LOG(ERROR) << "Invalid C2InfoBuffer::data";
902 return false;
903 }
904 return true;
905 }
906
907 // C2FrameData -> FrameData
objcpy(FrameData * d,const C2FrameData & s,BufferPoolSender * bufferPoolSender,std::list<BaseBlock> * baseBlocks,std::map<const void *,uint32_t> * baseBlockIndices)908 bool objcpy(FrameData* d, const C2FrameData& s,
909 BufferPoolSender* bufferPoolSender,
910 std::list<BaseBlock>* baseBlocks,
911 std::map<const void*, uint32_t>* baseBlockIndices) {
912 d->flags = static_cast<hidl_bitfield<FrameData::Flags>>(s.flags);
913 if (!objcpy(&d->ordinal, s.ordinal)) {
914 LOG(ERROR) << "Invalid C2FrameData::ordinal.";
915 return false;
916 }
917
918 d->buffers.resize(s.buffers.size());
919 size_t i = 0;
920 for (const std::shared_ptr<C2Buffer>& sBuffer : s.buffers) {
921 Buffer& dBuffer = d->buffers[i++];
922 if (!sBuffer) {
923 // A null (pointer to) C2Buffer corresponds to a Buffer with empty
924 // info and blocks.
925 dBuffer.info.resize(0);
926 dBuffer.blocks.resize(0);
927 continue;
928 }
929 if (!objcpy(
930 &dBuffer, *sBuffer,
931 bufferPoolSender, baseBlocks, baseBlockIndices)) {
932 LOG(ERROR) << "Invalid C2FrameData::buffers["
933 << i - 1 << "].";
934 return false;
935 }
936 }
937
938 if (!createParamsBlob(&d->configUpdate, s.configUpdate)) {
939 LOG(ERROR) << "Invalid C2FrameData::configUpdate.";
940 return false;
941 }
942
943 d->infoBuffers.resize(s.infoBuffers.size());
944 i = 0;
945 for (const C2InfoBuffer& sInfoBuffer : s.infoBuffers) {
946 InfoBuffer& dInfoBuffer = d->infoBuffers[i++];
947 if (!objcpy(&dInfoBuffer, sInfoBuffer,
948 bufferPoolSender, baseBlocks, baseBlockIndices)) {
949 LOG(ERROR) << "Invalid C2FrameData::infoBuffers["
950 << i - 1 << "].";
951 return false;
952 }
953 }
954
955 return true;
956 }
957
958 } // unnamed namespace
959
960 // DefaultBufferPoolSender's implementation
961
DefaultBufferPoolSender(const sp<IClientManager> & receiverManager,std::chrono::steady_clock::duration refreshInterval)962 DefaultBufferPoolSender::DefaultBufferPoolSender(
963 const sp<IClientManager>& receiverManager,
964 std::chrono::steady_clock::duration refreshInterval)
965 : mReceiverManager(receiverManager),
966 mRefreshInterval(refreshInterval) {
967 }
968
setReceiver(const sp<IClientManager> & receiverManager,std::chrono::steady_clock::duration refreshInterval)969 void DefaultBufferPoolSender::setReceiver(
970 const sp<IClientManager>& receiverManager,
971 std::chrono::steady_clock::duration refreshInterval) {
972 std::lock_guard<std::mutex> lock(mMutex);
973 if (mReceiverManager != receiverManager) {
974 mReceiverManager = receiverManager;
975 mConnections.clear();
976 }
977 mRefreshInterval = refreshInterval;
978 }
979
send(const std::shared_ptr<BufferPoolData> & bpData,BufferStatusMessage * bpMessage)980 ResultStatus DefaultBufferPoolSender::send(
981 const std::shared_ptr<BufferPoolData>& bpData,
982 BufferStatusMessage* bpMessage) {
983 int64_t connectionId = bpData->mConnectionId;
984 if (connectionId == 0) {
985 LOG(WARNING) << "registerSender -- invalid sender connection id (0).";
986 return ResultStatus::CRITICAL_ERROR;
987 }
988 std::lock_guard<std::mutex> lock(mMutex);
989 if (!mReceiverManager) {
990 LOG(ERROR) << "No access to receiver's BufferPool.";
991 return ResultStatus::NOT_FOUND;
992 }
993 if (!mSenderManager) {
994 mSenderManager = ClientManager::getInstance();
995 if (!mSenderManager) {
996 LOG(ERROR) << "Failed to retrieve local BufferPool ClientManager.";
997 return ResultStatus::CRITICAL_ERROR;
998 }
999 }
1000
1001 int64_t receiverConnectionId{0};
1002 auto foundConnection = mConnections.find(connectionId);
1003 bool isNewConnection = foundConnection == mConnections.end();
1004 std::chrono::steady_clock::time_point now =
1005 std::chrono::steady_clock::now();
1006 if (isNewConnection ||
1007 (now - foundConnection->second.lastSent > mRefreshInterval)) {
1008 // Initialize the bufferpool connection.
1009 ResultStatus rs =
1010 mSenderManager->registerSender(mReceiverManager,
1011 connectionId,
1012 &receiverConnectionId);
1013 if ((rs != ResultStatus::OK) && (rs != ResultStatus::ALREADY_EXISTS)) {
1014 LOG(WARNING) << "registerSender -- returned error: "
1015 << static_cast<int32_t>(rs)
1016 << ".";
1017 return rs;
1018 } else if (receiverConnectionId == 0) {
1019 LOG(WARNING) << "registerSender -- "
1020 "invalid receiver connection id (0).";
1021 return ResultStatus::CRITICAL_ERROR;
1022 } else {
1023 if (isNewConnection) {
1024 foundConnection = mConnections.try_emplace(
1025 connectionId, receiverConnectionId, now).first;
1026 } else {
1027 foundConnection->second.receiverConnectionId = receiverConnectionId;
1028 }
1029 }
1030 } else {
1031 receiverConnectionId = foundConnection->second.receiverConnectionId;
1032 }
1033
1034 uint64_t transactionId;
1035 int64_t timestampUs;
1036 ResultStatus rs = mSenderManager->postSend(
1037 receiverConnectionId, bpData, &transactionId, ×tampUs);
1038 if (rs != ResultStatus::OK) {
1039 LOG(ERROR) << "ClientManager::postSend -- returned error: "
1040 << static_cast<int32_t>(rs)
1041 << ".";
1042 mConnections.erase(foundConnection);
1043 return rs;
1044 }
1045 if (!bpMessage) {
1046 LOG(ERROR) << "Null output parameter for BufferStatusMessage.";
1047 mConnections.erase(foundConnection);
1048 return ResultStatus::CRITICAL_ERROR;
1049 }
1050 bpMessage->connectionId = receiverConnectionId;
1051 bpMessage->bufferId = bpData->mId;
1052 bpMessage->transactionId = transactionId;
1053 bpMessage->timestampUs = timestampUs;
1054 foundConnection->second.lastSent = now;
1055 return rs;
1056 }
1057
1058 // std::list<std::unique_ptr<C2Work>> -> WorkBundle
objcpy(WorkBundle * d,const std::list<std::unique_ptr<C2Work>> & s,BufferPoolSender * bufferPoolSender)1059 bool objcpy(
1060 WorkBundle* d,
1061 const std::list<std::unique_ptr<C2Work>>& s,
1062 BufferPoolSender* bufferPoolSender) {
1063 // baseBlocks holds a list of BaseBlock objects that Blocks can refer to.
1064 std::list<BaseBlock> baseBlocks;
1065
1066 // baseBlockIndices maps a raw pointer to native_handle_t or BufferPoolData
1067 // inside baseBlocks to the corresponding index into baseBlocks. The keys
1068 // (pointers) are used to identify blocks that have the same "base block" in
1069 // s, a list of C2Work objects. Because baseBlocks will be copied into a
1070 // hidl_vec eventually, the values of baseBlockIndices are zero-based
1071 // integer indices instead of list iterators.
1072 //
1073 // Note that the pointers can be raw because baseBlockIndices has a shorter
1074 // lifespan than all of base blocks.
1075 std::map<const void*, uint32_t> baseBlockIndices;
1076
1077 d->works.resize(s.size());
1078 size_t i = 0;
1079 for (const std::unique_ptr<C2Work>& sWork : s) {
1080 Work &dWork = d->works[i++];
1081 if (!sWork) {
1082 LOG(WARNING) << "Null C2Work encountered.";
1083 continue;
1084 }
1085
1086 // chain info is not in use currently.
1087
1088 // input
1089 if (!objcpy(&dWork.input, sWork->input,
1090 bufferPoolSender, &baseBlocks, &baseBlockIndices)) {
1091 LOG(ERROR) << "Invalid C2Work::input.";
1092 return false;
1093 }
1094
1095 // worklets
1096 if (sWork->worklets.size() == 0) {
1097 LOG(DEBUG) << "Work with no worklets.";
1098 } else {
1099 // Parcel the worklets.
1100 hidl_vec<Worklet> &dWorklets = dWork.worklets;
1101 dWorklets.resize(sWork->worklets.size());
1102 size_t j = 0;
1103 for (const std::unique_ptr<C2Worklet>& sWorklet : sWork->worklets)
1104 {
1105 if (!sWorklet) {
1106 LOG(WARNING) << "Null C2Work::worklets["
1107 << j << "].";
1108 continue;
1109 }
1110 Worklet &dWorklet = dWorklets[j++];
1111
1112 // component id
1113 dWorklet.componentId = static_cast<uint32_t>(
1114 sWorklet->component);
1115
1116 // tunings
1117 if (!createParamsBlob(&dWorklet.tunings, sWorklet->tunings)) {
1118 LOG(ERROR) << "Invalid C2Work::worklets["
1119 << j - 1 << "]->tunings.";
1120 return false;
1121 }
1122
1123 // failures
1124 dWorklet.failures.resize(sWorklet->failures.size());
1125 size_t k = 0;
1126 for (const std::unique_ptr<C2SettingResult>& sFailure :
1127 sWorklet->failures) {
1128 if (!sFailure) {
1129 LOG(WARNING) << "Null C2Work::worklets["
1130 << j - 1 << "]->failures["
1131 << k << "].";
1132 continue;
1133 }
1134 if (!objcpy(&dWorklet.failures[k++], *sFailure)) {
1135 LOG(ERROR) << "Invalid C2Work::worklets["
1136 << j - 1 << "]->failures["
1137 << k - 1 << "].";
1138 return false;
1139 }
1140 }
1141
1142 // output
1143 if (!objcpy(&dWorklet.output, sWorklet->output,
1144 bufferPoolSender, &baseBlocks, &baseBlockIndices)) {
1145 LOG(ERROR) << "Invalid C2Work::worklets["
1146 << j - 1 << "]->output.";
1147 return false;
1148 }
1149 }
1150 }
1151
1152 // worklets processed
1153 dWork.workletsProcessed = sWork->workletsProcessed;
1154
1155 // result
1156 dWork.result = static_cast<Status>(sWork->result);
1157 }
1158
1159 // Copy std::list<BaseBlock> to hidl_vec<BaseBlock>.
1160 {
1161 d->baseBlocks.resize(baseBlocks.size());
1162 size_t i = 0;
1163 for (const BaseBlock& baseBlock : baseBlocks) {
1164 d->baseBlocks[i++] = baseBlock;
1165 }
1166 }
1167
1168 return true;
1169 }
1170
1171 namespace /* unnamed */ {
1172
1173 struct C2BaseBlock {
1174 enum type_t {
1175 LINEAR,
1176 GRAPHIC,
1177 };
1178 type_t type;
1179 std::shared_ptr<C2LinearBlock> linear;
1180 std::shared_ptr<C2GraphicBlock> graphic;
1181 };
1182
1183 // hidl_handle -> C2Fence
1184 // Note: File descriptors are not duplicated. The original file descriptor must
1185 // not be closed before the transaction is complete.
objcpy(C2Fence * d,const hidl_handle & s)1186 bool objcpy(C2Fence* d, const hidl_handle& s) {
1187 // TODO: Implement.
1188 (void)s;
1189 *d = C2Fence();
1190 return true;
1191 }
1192
1193 // C2LinearBlock, vector<C2Param*>, C2Fence -> C2Buffer
createLinearBuffer(std::shared_ptr<C2Buffer> * buffer,const std::shared_ptr<C2LinearBlock> & block,const std::vector<C2Param * > & meta,const C2Fence & fence)1194 bool createLinearBuffer(
1195 std::shared_ptr<C2Buffer>* buffer,
1196 const std::shared_ptr<C2LinearBlock>& block,
1197 const std::vector<C2Param*>& meta,
1198 const C2Fence& fence) {
1199 // Check the block meta. It should have exactly 1 C2Info:
1200 // C2Hidl_RangeInfo.
1201 if ((meta.size() != 1) || !meta[0]) {
1202 LOG(ERROR) << "Invalid C2LinearBlock::meta.";
1203 return false;
1204 }
1205 if (meta[0]->size() != sizeof(C2Hidl_RangeInfo)) {
1206 LOG(ERROR) << "Invalid range info in C2LinearBlock.";
1207 return false;
1208 }
1209 C2Hidl_RangeInfo *rangeInfo =
1210 reinterpret_cast<C2Hidl_RangeInfo*>(meta[0]);
1211
1212 // Create C2Buffer from C2LinearBlock.
1213 *buffer = C2Buffer::CreateLinearBuffer(block->share(
1214 rangeInfo->offset, rangeInfo->length,
1215 fence));
1216 if (!(*buffer)) {
1217 LOG(ERROR) << "CreateLinearBuffer failed.";
1218 return false;
1219 }
1220 return true;
1221 }
1222
1223 // C2GraphicBlock, vector<C2Param*>, C2Fence -> C2Buffer
createGraphicBuffer(std::shared_ptr<C2Buffer> * buffer,const std::shared_ptr<C2GraphicBlock> & block,const std::vector<C2Param * > & meta,const C2Fence & fence)1224 bool createGraphicBuffer(
1225 std::shared_ptr<C2Buffer>* buffer,
1226 const std::shared_ptr<C2GraphicBlock>& block,
1227 const std::vector<C2Param*>& meta,
1228 const C2Fence& fence) {
1229 // Check the block meta. It should have exactly 1 C2Info:
1230 // C2Hidl_RectInfo.
1231 if ((meta.size() != 1) || !meta[0]) {
1232 LOG(ERROR) << "Invalid C2GraphicBlock::meta.";
1233 return false;
1234 }
1235 if (meta[0]->size() != sizeof(C2Hidl_RectInfo)) {
1236 LOG(ERROR) << "Invalid rect info in C2GraphicBlock.";
1237 return false;
1238 }
1239 C2Hidl_RectInfo *rectInfo =
1240 reinterpret_cast<C2Hidl_RectInfo*>(meta[0]);
1241
1242 // Create C2Buffer from C2GraphicBlock.
1243 *buffer = C2Buffer::CreateGraphicBuffer(block->share(
1244 C2Rect(rectInfo->width, rectInfo->height).
1245 at(rectInfo->left, rectInfo->top),
1246 fence));
1247 if (!(*buffer)) {
1248 LOG(ERROR) << "CreateGraphicBuffer failed.";
1249 return false;
1250 }
1251 return true;
1252 }
1253
1254 // Buffer -> C2Buffer
1255 // Note: The native handles will be cloned.
objcpy(std::shared_ptr<C2Buffer> * d,const Buffer & s,const std::vector<C2BaseBlock> & baseBlocks)1256 bool objcpy(std::shared_ptr<C2Buffer>* d, const Buffer& s,
1257 const std::vector<C2BaseBlock>& baseBlocks) {
1258 *d = nullptr;
1259
1260 // Currently, a non-null C2Buffer must contain exactly 1 block.
1261 if (s.blocks.size() == 0) {
1262 return true;
1263 } else if (s.blocks.size() != 1) {
1264 LOG(ERROR) << "Invalid Buffer: "
1265 "Currently, a C2Buffer must contain exactly 1 block.";
1266 return false;
1267 }
1268
1269 const Block &sBlock = s.blocks[0];
1270 if (sBlock.index >= baseBlocks.size()) {
1271 LOG(ERROR) << "Invalid Buffer::blocks[0].index: "
1272 "Array index out of range.";
1273 return false;
1274 }
1275 const C2BaseBlock &baseBlock = baseBlocks[sBlock.index];
1276
1277 // Parse meta.
1278 std::vector<C2Param*> sBlockMeta;
1279 if (!parseParamsBlob(&sBlockMeta, sBlock.meta)) {
1280 LOG(ERROR) << "Invalid Buffer::blocks[0].meta.";
1281 return false;
1282 }
1283
1284 // Copy fence.
1285 C2Fence dFence;
1286 if (!objcpy(&dFence, sBlock.fence)) {
1287 LOG(ERROR) << "Invalid Buffer::blocks[0].fence.";
1288 return false;
1289 }
1290
1291 // Construct a block.
1292 switch (baseBlock.type) {
1293 case C2BaseBlock::LINEAR:
1294 if (!createLinearBuffer(d, baseBlock.linear, sBlockMeta, dFence)) {
1295 LOG(ERROR) << "Invalid C2BaseBlock::linear.";
1296 return false;
1297 }
1298 break;
1299 case C2BaseBlock::GRAPHIC:
1300 if (!createGraphicBuffer(d, baseBlock.graphic, sBlockMeta, dFence)) {
1301 LOG(ERROR) << "Invalid C2BaseBlock::graphic.";
1302 return false;
1303 }
1304 break;
1305 default:
1306 LOG(ERROR) << "Invalid C2BaseBlock::type.";
1307 return false;
1308 }
1309
1310 // Parse info
1311 std::vector<C2Param*> params;
1312 if (!parseParamsBlob(¶ms, s.info)) {
1313 LOG(ERROR) << "Invalid Buffer::info.";
1314 return false;
1315 }
1316 for (C2Param* param : params) {
1317 if (param == nullptr) {
1318 LOG(ERROR) << "Null param in Buffer::info.";
1319 return false;
1320 }
1321 std::shared_ptr<C2Param> c2param{
1322 C2Param::Copy(*param).release()};
1323 if (!c2param) {
1324 LOG(ERROR) << "Invalid param in Buffer::info.";
1325 return false;
1326 }
1327 c2_status_t status =
1328 (*d)->setInfo(std::static_pointer_cast<C2Info>(c2param));
1329 if (status != C2_OK) {
1330 LOG(ERROR) << "C2Buffer::setInfo failed.";
1331 return false;
1332 }
1333 }
1334
1335 return true;
1336 }
1337
1338 // InfoBuffer -> C2InfoBuffer
objcpy(std::vector<C2InfoBuffer> * d,const InfoBuffer & s,const std::vector<C2BaseBlock> & baseBlocks)1339 bool objcpy(std::vector<C2InfoBuffer> *d, const InfoBuffer& s,
1340 const std::vector<C2BaseBlock>& baseBlocks) {
1341
1342 // Currently, a non-null C2InfoBufer must contain exactly 1 block.
1343 if (s.buffer.blocks.size() == 0) {
1344 return true;
1345 } else if (s.buffer.blocks.size() != 1) {
1346 LOG(ERROR) << "Invalid InfoBuffer::Buffer "
1347 "Currently, a C2InfoBuffer must contain exactly 1 block.";
1348 return false;
1349 }
1350
1351 const Block &sBlock = s.buffer.blocks[0];
1352 if (sBlock.index >= baseBlocks.size()) {
1353 LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].index: "
1354 "Array index out of range.";
1355 return false;
1356 }
1357 const C2BaseBlock &baseBlock = baseBlocks[sBlock.index];
1358
1359 // Parse meta.
1360 std::vector<C2Param*> sBlockMeta;
1361 if (!parseParamsBlob(&sBlockMeta, sBlock.meta)) {
1362 LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].meta.";
1363 return false;
1364 }
1365
1366 // Copy fence.
1367 C2Fence dFence;
1368 if (!objcpy(&dFence, sBlock.fence)) {
1369 LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].fence.";
1370 return false;
1371 }
1372
1373 // Construct a block.
1374 switch (baseBlock.type) {
1375 case C2BaseBlock::LINEAR:
1376 if (sBlockMeta.size() == 1 && sBlockMeta[0] != nullptr &&
1377 sBlockMeta[0]->size() == sizeof(C2Hidl_RangeInfo)) {
1378 C2Hidl_RangeInfo *rangeInfo =
1379 reinterpret_cast<C2Hidl_RangeInfo*>(sBlockMeta[0]);
1380 d->emplace_back(C2InfoBuffer::CreateLinearBuffer(
1381 s.index,
1382 baseBlock.linear->share(
1383 rangeInfo->offset, rangeInfo->length, dFence)));
1384 return true;
1385 }
1386 LOG(ERROR) << "Invalid Meta for C2BaseBlock::Linear InfoBuffer.";
1387 break;
1388 case C2BaseBlock::GRAPHIC:
1389 // It's not used now
1390 LOG(ERROR) << "Non-Used C2BaseBlock::type for InfoBuffer.";
1391 break;
1392 default:
1393 LOG(ERROR) << "Invalid C2BaseBlock::type for InfoBuffer.";
1394 break;
1395 }
1396
1397 return false;
1398 }
1399
1400 // FrameData -> C2FrameData
objcpy(C2FrameData * d,const FrameData & s,const std::vector<C2BaseBlock> & baseBlocks)1401 bool objcpy(C2FrameData* d, const FrameData& s,
1402 const std::vector<C2BaseBlock>& baseBlocks) {
1403 d->flags = static_cast<C2FrameData::flags_t>(s.flags);
1404 if (!objcpy(&d->ordinal, s.ordinal)) {
1405 LOG(ERROR) << "Invalid FrameData::ordinal.";
1406 return false;
1407 }
1408 d->buffers.clear();
1409 d->buffers.reserve(s.buffers.size());
1410 for (const Buffer& sBuffer : s.buffers) {
1411 std::shared_ptr<C2Buffer> dBuffer;
1412 if (!objcpy(&dBuffer, sBuffer, baseBlocks)) {
1413 LOG(ERROR) << "Invalid FrameData::buffers.";
1414 return false;
1415 }
1416 d->buffers.emplace_back(dBuffer);
1417 }
1418
1419 std::vector<C2Param*> params;
1420 if (!parseParamsBlob(¶ms, s.configUpdate)) {
1421 LOG(ERROR) << "Invalid FrameData::configUpdate.";
1422 return false;
1423 }
1424 d->configUpdate.clear();
1425 for (C2Param* param : params) {
1426 d->configUpdate.emplace_back(C2Param::Copy(*param));
1427 if (!d->configUpdate.back()) {
1428 LOG(ERROR) << "Unexpected error while parsing "
1429 "FrameData::configUpdate.";
1430 return false;
1431 }
1432 }
1433
1434 d->infoBuffers.clear();
1435 if (s.infoBuffers.size() == 0) {
1436 // InfoBuffer is optional
1437 return true;
1438 }
1439 d->infoBuffers.reserve(s.infoBuffers.size());
1440 for (const InfoBuffer &sInfoBuffer: s.infoBuffers) {
1441 if (!objcpy(&(d->infoBuffers), sInfoBuffer, baseBlocks)) {
1442 LOG(ERROR) << "Invalid Framedata::infoBuffers.";
1443 return false;
1444 }
1445 }
1446 return true;
1447 }
1448
1449 // BaseBlock -> C2BaseBlock
objcpy(C2BaseBlock * d,const BaseBlock & s)1450 bool objcpy(C2BaseBlock* d, const BaseBlock& s) {
1451 switch (s.getDiscriminator()) {
1452 case BaseBlock::hidl_discriminator::nativeBlock: {
1453 native_handle_t* sHandle =
1454 native_handle_clone(s.nativeBlock());
1455 if (sHandle == nullptr) {
1456 LOG(ERROR) << "Null BaseBlock::nativeBlock.";
1457 return false;
1458 }
1459 const C2Handle *sC2Handle =
1460 reinterpret_cast<const C2Handle*>(sHandle);
1461
1462 d->linear = _C2BlockFactory::CreateLinearBlock(sC2Handle);
1463 if (d->linear) {
1464 d->type = C2BaseBlock::LINEAR;
1465 return true;
1466 }
1467
1468 d->graphic = _C2BlockFactory::CreateGraphicBlock(sC2Handle);
1469 if (d->graphic) {
1470 d->type = C2BaseBlock::GRAPHIC;
1471 return true;
1472 }
1473
1474 LOG(ERROR) << "Unknown handle type in BaseBlock::nativeBlock.";
1475 if (sHandle) {
1476 native_handle_close(sHandle);
1477 native_handle_delete(sHandle);
1478 }
1479 return false;
1480 }
1481 case BaseBlock::hidl_discriminator::pooledBlock: {
1482 const BufferStatusMessage &bpMessage =
1483 s.pooledBlock();
1484 sp<ClientManager> bp = ClientManager::getInstance();
1485 std::shared_ptr<BufferPoolData> bpData;
1486 native_handle_t *cHandle;
1487 ResultStatus bpStatus = bp->receive(
1488 bpMessage.connectionId,
1489 bpMessage.transactionId,
1490 bpMessage.bufferId,
1491 bpMessage.timestampUs,
1492 &cHandle,
1493 &bpData);
1494 if (bpStatus != ResultStatus::OK) {
1495 LOG(ERROR) << "Failed to receive buffer from bufferpool -- "
1496 << "resultStatus = " << underlying_value(bpStatus)
1497 << ".";
1498 return false;
1499 } else if (!bpData) {
1500 LOG(ERROR) << "No data in bufferpool transaction.";
1501 return false;
1502 }
1503
1504 d->linear = _C2BlockFactory::CreateLinearBlock(cHandle, bpData);
1505 if (d->linear) {
1506 d->type = C2BaseBlock::LINEAR;
1507 return true;
1508 }
1509
1510 d->graphic = _C2BlockFactory::CreateGraphicBlock(cHandle, bpData);
1511 if (d->graphic) {
1512 d->type = C2BaseBlock::GRAPHIC;
1513 return true;
1514 }
1515 if (cHandle) {
1516 // Though we got cloned handle, creating block failed.
1517 native_handle_close(cHandle);
1518 native_handle_delete(cHandle);
1519 }
1520
1521 LOG(ERROR) << "Unknown handle type in BaseBlock::pooledBlock.";
1522 return false;
1523 }
1524 default:
1525 LOG(ERROR) << "Unrecognized BaseBlock's discriminator with "
1526 << "underlying value "
1527 << underlying_value(s.getDiscriminator()) << ".";
1528 return false;
1529 }
1530 }
1531
1532 } // unnamed namespace
1533
1534 // WorkBundle -> std::list<std::unique_ptr<C2Work>>
objcpy(std::list<std::unique_ptr<C2Work>> * d,const WorkBundle & s)1535 bool objcpy(std::list<std::unique_ptr<C2Work>>* d, const WorkBundle& s) {
1536 // Convert BaseBlocks to C2BaseBlocks.
1537 std::vector<C2BaseBlock> dBaseBlocks(s.baseBlocks.size());
1538 for (size_t i = 0; i < s.baseBlocks.size(); ++i) {
1539 if (!objcpy(&dBaseBlocks[i], s.baseBlocks[i])) {
1540 LOG(ERROR) << "Invalid WorkBundle::baseBlocks["
1541 << i << "].";
1542 return false;
1543 }
1544 }
1545
1546 d->clear();
1547 for (const Work& sWork : s.works) {
1548 d->emplace_back(std::make_unique<C2Work>());
1549 C2Work& dWork = *d->back();
1550
1551 // chain info is not in use currently.
1552
1553 // input
1554 if (!objcpy(&dWork.input, sWork.input, dBaseBlocks)) {
1555 LOG(ERROR) << "Invalid Work::input.";
1556 return false;
1557 }
1558
1559 // worklet(s)
1560 dWork.worklets.clear();
1561 for (const Worklet& sWorklet : sWork.worklets) {
1562 std::unique_ptr<C2Worklet> dWorklet = std::make_unique<C2Worklet>();
1563
1564 // component id
1565 dWorklet->component = static_cast<c2_node_id_t>(
1566 sWorklet.componentId);
1567
1568 // tunings
1569 if (!copyParamsFromBlob(&dWorklet->tunings, sWorklet.tunings)) {
1570 LOG(ERROR) << "Invalid Worklet::tunings";
1571 return false;
1572 }
1573
1574 // failures
1575 dWorklet->failures.clear();
1576 dWorklet->failures.reserve(sWorklet.failures.size());
1577 for (const SettingResult& sFailure : sWorklet.failures) {
1578 std::unique_ptr<C2SettingResult> dFailure;
1579 if (!objcpy(&dFailure, sFailure)) {
1580 LOG(ERROR) << "Invalid Worklet::failures.";
1581 return false;
1582 }
1583 dWorklet->failures.emplace_back(std::move(dFailure));
1584 }
1585
1586 // output
1587 if (!objcpy(&dWorklet->output, sWorklet.output, dBaseBlocks)) {
1588 LOG(ERROR) << "Invalid Worklet::output.";
1589 return false;
1590 }
1591
1592 dWork.worklets.emplace_back(std::move(dWorklet));
1593 }
1594
1595 // workletsProcessed
1596 dWork.workletsProcessed = sWork.workletsProcessed;
1597
1598 // result
1599 dWork.result = static_cast<c2_status_t>(sWork.result);
1600 }
1601
1602 return true;
1603 }
1604
1605 constexpr size_t PARAMS_ALIGNMENT = 8; // 64-bit alignment
1606 static_assert(PARAMS_ALIGNMENT % alignof(C2Param) == 0, "C2Param alignment mismatch");
1607 static_assert(PARAMS_ALIGNMENT % alignof(C2Info) == 0, "C2Param alignment mismatch");
1608 static_assert(PARAMS_ALIGNMENT % alignof(C2Tuning) == 0, "C2Param alignment mismatch");
1609
1610 // Params -> std::vector<C2Param*>
parseParamsBlob(std::vector<C2Param * > * params,const hidl_vec<uint8_t> & blob)1611 bool parseParamsBlob(std::vector<C2Param*> *params, const hidl_vec<uint8_t> &blob) {
1612 // assuming blob is const here
1613 size_t size = blob.size();
1614 size_t ix = 0;
1615 const uint8_t *data = blob.data();
1616 C2Param *p = nullptr;
1617
1618 do {
1619 p = C2ParamUtils::ParseFirst(data + ix, size - ix);
1620 if (p) {
1621 params->emplace_back(p);
1622 ix += p->size();
1623 ix = align(ix, PARAMS_ALIGNMENT);
1624 }
1625 } while (p);
1626
1627 if (ix != size) {
1628 LOG(ERROR) << "parseParamsBlob -- inconsistent sizes.";
1629 return false;
1630 }
1631 return true;
1632 }
1633
1634 namespace /* unnamed */ {
1635
1636 /**
1637 * Concatenates a list of C2Params into a params blob. T is a container type
1638 * whose member type is compatible with C2Param*.
1639 *
1640 * \param[out] blob target blob
1641 * \param[in] params parameters to concatenate
1642 * \retval C2_OK if the blob was successfully created
1643 * \retval C2_BAD_VALUE if the blob was not successful created (this only
1644 * happens if the parameters were not const)
1645 */
1646 template <typename T>
_createParamsBlob(hidl_vec<uint8_t> * blob,const T & params)1647 bool _createParamsBlob(hidl_vec<uint8_t> *blob, const T ¶ms) {
1648 // assuming the parameter values are const
1649 size_t size = 0;
1650 for (const auto &p : params) {
1651 if (!p) {
1652 continue;
1653 }
1654 size += p->size();
1655 size = align(size, PARAMS_ALIGNMENT);
1656 }
1657 blob->resize(size);
1658 size_t ix = 0;
1659 for (const auto &p : params) {
1660 if (!p) {
1661 continue;
1662 }
1663 // NEVER overwrite even if param values (e.g. size) changed
1664 size_t paramSize = std::min(p->size(), size - ix);
1665 std::copy(
1666 reinterpret_cast<const uint8_t*>(&*p),
1667 reinterpret_cast<const uint8_t*>(&*p) + paramSize,
1668 &(*blob)[ix]);
1669 ix += paramSize;
1670 ix = align(ix, PARAMS_ALIGNMENT);
1671 }
1672 blob->resize(ix);
1673 if (ix != size) {
1674 LOG(ERROR) << "createParamsBlob -- inconsistent sizes.";
1675 return false;
1676 }
1677 return true;
1678 }
1679
1680 /**
1681 * Parses a params blob and create a vector of new T objects that contain copies
1682 * of the params in the blob. T is C2Param or its compatible derived class.
1683 *
1684 * \param[out] params the resulting vector
1685 * \param[in] blob parameter blob to parse
1686 * \retval C2_OK if the full blob was parsed and params was constructed
1687 * \retval C2_BAD_VALUE otherwise
1688 */
1689 template <typename T>
_copyParamsFromBlob(std::vector<std::unique_ptr<T>> * params,Params blob)1690 bool _copyParamsFromBlob(
1691 std::vector<std::unique_ptr<T>>* params,
1692 Params blob) {
1693
1694 std::vector<C2Param*> paramPointers;
1695 if (!parseParamsBlob(¶mPointers, blob)) {
1696 LOG(ERROR) << "copyParamsFromBlob -- failed to parse.";
1697 return false;
1698 }
1699
1700 params->resize(paramPointers.size());
1701 size_t i = 0;
1702 for (C2Param* const& paramPointer : paramPointers) {
1703 if (!paramPointer) {
1704 LOG(ERROR) << "copyParamsFromBlob -- null paramPointer.";
1705 return false;
1706 }
1707 (*params)[i++].reset(reinterpret_cast<T*>(
1708 C2Param::Copy(*paramPointer).release()));
1709 }
1710 return true;
1711 }
1712
1713 } // unnamed namespace
1714
1715 // std::vector<const C2Param*> -> Params
createParamsBlob(hidl_vec<uint8_t> * blob,const std::vector<const C2Param * > & params)1716 bool createParamsBlob(
1717 hidl_vec<uint8_t> *blob,
1718 const std::vector<const C2Param*> ¶ms) {
1719 return _createParamsBlob(blob, params);
1720 }
1721
1722 // std::vector<C2Param*> -> Params
createParamsBlob(hidl_vec<uint8_t> * blob,const std::vector<C2Param * > & params)1723 bool createParamsBlob(
1724 hidl_vec<uint8_t> *blob,
1725 const std::vector<C2Param*> ¶ms) {
1726 return _createParamsBlob(blob, params);
1727 }
1728
1729 // std::vector<std::unique_ptr<C2Param>> -> Params
createParamsBlob(hidl_vec<uint8_t> * blob,const std::vector<std::unique_ptr<C2Param>> & params)1730 bool createParamsBlob(
1731 hidl_vec<uint8_t> *blob,
1732 const std::vector<std::unique_ptr<C2Param>> ¶ms) {
1733 return _createParamsBlob(blob, params);
1734 }
1735
1736 // std::vector<std::unique_ptr<C2Tuning>> -> Params
createParamsBlob(hidl_vec<uint8_t> * blob,const std::vector<std::unique_ptr<C2Tuning>> & params)1737 bool createParamsBlob(
1738 hidl_vec<uint8_t> *blob,
1739 const std::vector<std::unique_ptr<C2Tuning>> ¶ms) {
1740 return _createParamsBlob(blob, params);
1741 }
1742
1743 // std::vector<std::shared_ptr<const C2Info>> -> Params
createParamsBlob(hidl_vec<uint8_t> * blob,const std::vector<std::shared_ptr<const C2Info>> & params)1744 bool createParamsBlob(
1745 hidl_vec<uint8_t> *blob,
1746 const std::vector<std::shared_ptr<const C2Info>> ¶ms) {
1747 return _createParamsBlob(blob, params);
1748 }
1749
1750 // Params -> std::vector<std::unique_ptr<C2Param>>
copyParamsFromBlob(std::vector<std::unique_ptr<C2Param>> * params,Params blob)1751 bool copyParamsFromBlob(
1752 std::vector<std::unique_ptr<C2Param>>* params,
1753 Params blob) {
1754 return _copyParamsFromBlob(params, blob);
1755 }
1756
1757 // Params -> std::vector<std::unique_ptr<C2Tuning>>
copyParamsFromBlob(std::vector<std::unique_ptr<C2Tuning>> * params,Params blob)1758 bool copyParamsFromBlob(
1759 std::vector<std::unique_ptr<C2Tuning>>* params,
1760 Params blob) {
1761 return _copyParamsFromBlob(params, blob);
1762 }
1763
1764 // Params -> update std::vector<std::unique_ptr<C2Param>>
updateParamsFromBlob(const std::vector<C2Param * > & params,const Params & blob)1765 bool updateParamsFromBlob(
1766 const std::vector<C2Param*>& params,
1767 const Params& blob) {
1768 std::unordered_map<uint32_t, C2Param*> index2param;
1769 for (C2Param* const& param : params) {
1770 if (!param) {
1771 LOG(ERROR) << "updateParamsFromBlob -- null output param.";
1772 return false;
1773 }
1774 if (index2param.find(param->index()) == index2param.end()) {
1775 index2param.emplace(param->index(), param);
1776 }
1777 }
1778
1779 std::vector<C2Param*> paramPointers;
1780 if (!parseParamsBlob(¶mPointers, blob)) {
1781 LOG(ERROR) << "updateParamsFromBlob -- failed to parse.";
1782 return false;
1783 }
1784
1785 for (C2Param* const& paramPointer : paramPointers) {
1786 if (!paramPointer) {
1787 LOG(ERROR) << "updateParamsFromBlob -- null input param.";
1788 return false;
1789 }
1790 decltype(index2param)::iterator i = index2param.find(
1791 paramPointer->index());
1792 if (i == index2param.end()) {
1793 LOG(DEBUG) << "updateParamsFromBlob -- index "
1794 << paramPointer->index() << " not found. Skipping...";
1795 continue;
1796 }
1797 if (!i->second->updateFrom(*paramPointer)) {
1798 LOG(ERROR) << "updateParamsFromBlob -- size mismatch: "
1799 << params.size() << " vs " << paramPointer->size()
1800 << " (index = " << i->first << ").";
1801 return false;
1802 }
1803 }
1804 return true;
1805 }
1806
1807 // Convert BufferPool ResultStatus to c2_status_t.
toC2Status(ResultStatus rs)1808 c2_status_t toC2Status(ResultStatus rs) {
1809 switch (rs) {
1810 case ResultStatus::OK:
1811 return C2_OK;
1812 case ResultStatus::NO_MEMORY:
1813 return C2_NO_MEMORY;
1814 case ResultStatus::ALREADY_EXISTS:
1815 return C2_DUPLICATE;
1816 case ResultStatus::NOT_FOUND:
1817 return C2_NOT_FOUND;
1818 case ResultStatus::CRITICAL_ERROR:
1819 return C2_CORRUPTED;
1820 default:
1821 LOG(WARNING) << "Unrecognized BufferPool ResultStatus: "
1822 << static_cast<int32_t>(rs) << ".";
1823 return C2_CORRUPTED;
1824 }
1825 }
1826
1827 namespace /* unnamed */ {
1828
1829 template <typename BlockProcessor>
forEachBlock(C2FrameData & frameData,BlockProcessor process)1830 void forEachBlock(C2FrameData& frameData,
1831 BlockProcessor process) {
1832 for (const std::shared_ptr<C2Buffer>& buffer : frameData.buffers) {
1833 if (buffer) {
1834 for (const C2ConstGraphicBlock& block :
1835 buffer->data().graphicBlocks()) {
1836 process(block);
1837 }
1838 }
1839 }
1840 }
1841
1842 template <typename BlockProcessor>
forEachBlock(const std::list<std::unique_ptr<C2Work>> & workList,BlockProcessor process,bool processInput,bool processOutput)1843 void forEachBlock(const std::list<std::unique_ptr<C2Work>>& workList,
1844 BlockProcessor process,
1845 bool processInput, bool processOutput) {
1846 for (const std::unique_ptr<C2Work>& work : workList) {
1847 if (!work) {
1848 continue;
1849 }
1850 if (processInput) {
1851 forEachBlock(work->input, process);
1852 }
1853 if (processOutput) {
1854 for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
1855 if (worklet) {
1856 forEachBlock(worklet->output,
1857 process);
1858 }
1859 }
1860 }
1861 }
1862 }
1863
1864 } // unnamed namespace
1865
beginTransferBufferQueueBlock(const C2ConstGraphicBlock & block)1866 bool beginTransferBufferQueueBlock(const C2ConstGraphicBlock& block) {
1867 std::shared_ptr<_C2BlockPoolData> data =
1868 _C2BlockFactory::GetGraphicBlockPoolData(block);
1869 if (data && _C2BlockFactory::GetBufferQueueData(data)) {
1870 _C2BlockFactory::BeginTransferBlockToClient(data);
1871 return true;
1872 }
1873 return false;
1874 }
1875
beginTransferBufferQueueBlocks(const std::list<std::unique_ptr<C2Work>> & workList,bool processInput,bool processOutput)1876 void beginTransferBufferQueueBlocks(
1877 const std::list<std::unique_ptr<C2Work>>& workList,
1878 bool processInput, bool processOutput) {
1879 forEachBlock(workList, beginTransferBufferQueueBlock,
1880 processInput, processOutput);
1881 }
1882
endTransferBufferQueueBlock(const C2ConstGraphicBlock & block,bool transfer)1883 bool endTransferBufferQueueBlock(
1884 const C2ConstGraphicBlock& block,
1885 bool transfer) {
1886 std::shared_ptr<_C2BlockPoolData> data =
1887 _C2BlockFactory::GetGraphicBlockPoolData(block);
1888 if (data && _C2BlockFactory::GetBufferQueueData(data)) {
1889 _C2BlockFactory::EndTransferBlockToClient(data, transfer);
1890 return true;
1891 }
1892 return false;
1893 }
1894
endTransferBufferQueueBlocks(const std::list<std::unique_ptr<C2Work>> & workList,bool transfer,bool processInput,bool processOutput)1895 void endTransferBufferQueueBlocks(
1896 const std::list<std::unique_ptr<C2Work>>& workList,
1897 bool transfer,
1898 bool processInput, bool processOutput) {
1899 forEachBlock(workList,
1900 std::bind(endTransferBufferQueueBlock,
1901 std::placeholders::_1, transfer),
1902 processInput, processOutput);
1903 }
1904
displayBufferQueueBlock(const C2ConstGraphicBlock & block)1905 bool displayBufferQueueBlock(const C2ConstGraphicBlock& block) {
1906 std::shared_ptr<_C2BlockPoolData> data =
1907 _C2BlockFactory::GetGraphicBlockPoolData(block);
1908 if (data && _C2BlockFactory::GetBufferQueueData(data)) {
1909 _C2BlockFactory::DisplayBlockToBufferQueue(data);
1910 return true;
1911 }
1912 return false;
1913 }
1914
1915 } // namespace utils
1916 } // namespace V1_0
1917 } // namespace c2
1918 } // namespace media
1919 } // namespace hardware
1920 } // namespace android
1921
1922