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, &timestampUs);
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(&params, 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(&params, 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 &params) {
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*> &params) {
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*> &params) {
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>> &params) {
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>> &params) {
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>> &params) {
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(&paramPointers, 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(&paramPointers, 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