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