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