• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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_TAG "ApexCodecs"
18 // #define LOG_NDEBUG 0
19 #include <android-base/logging.h>
20 
21 #include <new>
22 #include <map>
23 #include <vector>
24 
25 #include <C2ParamInternal.h>
26 #include <android_media_swcodec_flags.h>
27 
28 #include <android-base/no_destructor.h>
29 #include <apex/ApexCodecs.h>
30 #include <apex/ApexCodecsImpl.h>
31 #include <apex/ApexCodecsParam.h>
32 
33 // TODO: remove when we have real implementations
34 #pragma clang diagnostic push
35 #pragma clang diagnostic ignored "-Wunused-parameter"
36 
37 using ::android::apexcodecs::ApexComponentIntf;
38 using ::android::apexcodecs::ApexComponentStoreIntf;
39 using ::android::base::ERROR;
40 
41 struct ApexCodec_Component {
ApexCodec_ComponentApexCodec_Component42     explicit ApexCodec_Component(std::unique_ptr<ApexComponentIntf> &&comp)
43         : mComponent(std::move(comp)) {
44     }
45 
startApexCodec_Component46     ApexCodec_Status start() {
47         return mComponent->start();
48     }
49 
flushApexCodec_Component50     ApexCodec_Status flush() {
51         return mComponent->flush();
52     }
53 
resetApexCodec_Component54     ApexCodec_Status reset() {
55         return mComponent->reset();
56     }
57 
58 private:
59     std::unique_ptr<ApexComponentIntf> mComponent;
60 };
61 
62 struct ApexCodec_ComponentStore {
ApexCodec_ComponentStoreApexCodec_ComponentStore63     ApexCodec_ComponentStore() : mStore((ApexComponentStoreIntf *)GetApexComponentStore()) {
64         if (mStore == nullptr) {
65             return;
66         }
67         mC2Traits = mStore->listComponents();
68         mTraits.reserve(mC2Traits.size());
69         for (const std::shared_ptr<const C2Component::Traits> &trait : mC2Traits) {
70             mTraits.push_back(ApexCodec_ComponentTraits{
71                 trait->name.c_str(),                // name
72                 trait->mediaType.c_str(),           // mediaType
73                 (ApexCodec_Kind)trait->kind,        // kind
74                 (ApexCodec_Domain)trait->domain,    // domain
75             });
76         }
77     }
78 
getTraitsApexCodec_ComponentStore79     ApexCodec_ComponentTraits *getTraits(size_t index) {
80         if (mStore == nullptr) {
81             return nullptr;
82         }
83         if (index < mTraits.size()) {
84             return mTraits.data() + index;
85         } else {
86             return nullptr;
87         }
88     }
89 
createComponentApexCodec_ComponentStore90     std::unique_ptr<ApexComponentIntf> createComponent(const char *name) {
91         if (mStore == nullptr) {
92             return nullptr;
93         }
94         return mStore->createComponent(name);
95     }
96 private:
97     ApexComponentStoreIntf *mStore;
98     std::vector<std::shared_ptr<const C2Component::Traits>> mC2Traits;
99     std::vector<ApexCodec_ComponentTraits> mTraits;
100 };
101 
ApexCodec_GetComponentStore()102 ApexCodec_ComponentStore *ApexCodec_GetComponentStore() {
103     ::android::base::NoDestructor<ApexCodec_ComponentStore> store;
104     return store.get();
105 }
106 
ApexCodec_Traits_get(ApexCodec_ComponentStore * store,size_t index)107 ApexCodec_ComponentTraits *ApexCodec_Traits_get(
108         ApexCodec_ComponentStore *store, size_t index) {
109     if (!android::media::swcodec::flags::apexcodecs_base()) {
110         return nullptr;
111     }
112     return store->getTraits(index);
113 }
114 
ApexCodec_Component_create(ApexCodec_ComponentStore * store,const char * name,ApexCodec_Component ** comp)115 ApexCodec_Status ApexCodec_Component_create(
116         ApexCodec_ComponentStore *store, const char *name, ApexCodec_Component **comp) {
117     if (!android::media::swcodec::flags::apexcodecs_base()) {
118         return APEXCODEC_STATUS_NOT_FOUND;
119     }
120     if (store == nullptr) {
121         LOG(ERROR) << "ApexCodec_Component_create: store is nullptr";
122         return APEXCODEC_STATUS_BAD_VALUE;
123     }
124     if (name == nullptr) {
125         LOG(ERROR) << "ApexCodec_Component_create: name is nullptr";
126         return APEXCODEC_STATUS_BAD_VALUE;
127     }
128     if (comp == nullptr) {
129         LOG(ERROR) << "ApexCodec_Component_create: comp is nullptr";
130         return APEXCODEC_STATUS_BAD_VALUE;
131     }
132     *comp = nullptr;
133     std::unique_ptr<ApexComponentIntf> compIntf = store->createComponent(name);
134     if (compIntf == nullptr) {
135         return APEXCODEC_STATUS_NOT_FOUND;
136     }
137     *comp = new ApexCodec_Component(std::move(compIntf));
138     return APEXCODEC_STATUS_OK;
139 }
140 
ApexCodec_Component_destroy(ApexCodec_Component * comp)141 void ApexCodec_Component_destroy(ApexCodec_Component *comp) {
142     delete comp;
143 }
144 
ApexCodec_Component_start(ApexCodec_Component * comp)145 ApexCodec_Status ApexCodec_Component_start(ApexCodec_Component *comp) {
146     if (comp == nullptr) {
147         return APEXCODEC_STATUS_BAD_VALUE;
148     }
149     return comp->start();
150 }
151 
ApexCodec_Component_flush(ApexCodec_Component * comp)152 ApexCodec_Status ApexCodec_Component_flush(ApexCodec_Component *comp) {
153     if (comp == nullptr) {
154         return APEXCODEC_STATUS_BAD_VALUE;
155     }
156     return comp->flush();
157 }
158 
ApexCodec_Component_reset(ApexCodec_Component * comp)159 ApexCodec_Status ApexCodec_Component_reset(ApexCodec_Component *comp) {
160     if (comp == nullptr) {
161         return APEXCODEC_STATUS_BAD_VALUE;
162     }
163     return comp->reset();
164 }
165 
ApexCodec_Component_getConfigurable(ApexCodec_Component * comp)166 ApexCodec_Configurable *ApexCodec_Component_getConfigurable(
167         ApexCodec_Component *comp) {
168     return nullptr;
169 }
170 
171 struct ApexCodec_Buffer {
172 public:
ApexCodec_BufferApexCodec_Buffer173     ApexCodec_Buffer()
174           : mType(APEXCODEC_BUFFER_TYPE_EMPTY) {
175     }
176 
~ApexCodec_BufferApexCodec_Buffer177     ~ApexCodec_Buffer() {
178     }
179 
clearApexCodec_Buffer180     void clear() {
181         mType = APEXCODEC_BUFFER_TYPE_EMPTY;
182         mBufferInfo.reset();
183         mLinearBuffer = {};
184         mGraphicBuffer = nullptr;
185         mConfigUpdates.reset();
186         mOwnedConfigUpdates.reset();
187     }
188 
getTypeApexCodec_Buffer189     ApexCodec_BufferType getType() const {
190         return mType;
191     }
192 
setBufferInfoApexCodec_Buffer193     void setBufferInfo(ApexCodec_BufferFlags flags, uint64_t frameIndex, uint64_t timestampUs) {
194         mBufferInfo.emplace(BufferInfo{flags, frameIndex, timestampUs});
195     }
196 
setLinearBufferApexCodec_Buffer197     ApexCodec_Status setLinearBuffer(const ApexCodec_LinearBuffer *linearBuffer) {
198         if (mType != APEXCODEC_BUFFER_TYPE_EMPTY) {
199             return APEXCODEC_STATUS_BAD_STATE;
200         }
201         mType = APEXCODEC_BUFFER_TYPE_LINEAR;
202         if (linearBuffer == nullptr) {
203             mLinearBuffer.data = nullptr;
204             mLinearBuffer.size = 0;
205         } else {
206             mLinearBuffer = *linearBuffer;
207         }
208         return APEXCODEC_STATUS_OK;
209     }
210 
setGraphicBufferApexCodec_Buffer211     ApexCodec_Status setGraphicBuffer(AHardwareBuffer *graphicBuffer) {
212         if (mType != APEXCODEC_BUFFER_TYPE_EMPTY) {
213             return APEXCODEC_STATUS_BAD_STATE;
214         }
215         mType = APEXCODEC_BUFFER_TYPE_GRAPHIC;
216         mGraphicBuffer = graphicBuffer;
217         return APEXCODEC_STATUS_OK;
218     }
219 
setConfigUpdatesApexCodec_Buffer220     ApexCodec_Status setConfigUpdates(const ApexCodec_LinearBuffer *configUpdates) {
221         if (configUpdates == nullptr) {
222             return APEXCODEC_STATUS_BAD_VALUE;
223         }
224         if (mConfigUpdates.has_value()) {
225             return APEXCODEC_STATUS_BAD_STATE;
226         }
227         mOwnedConfigUpdates.reset();
228         mConfigUpdates.emplace(*configUpdates);
229         return APEXCODEC_STATUS_OK;
230     }
231 
getBufferInfoApexCodec_Buffer232     ApexCodec_Status getBufferInfo(
233             ApexCodec_BufferFlags *outFlags,
234             uint64_t *outFrameIndex,
235             uint64_t *outTimestampUs) const {
236         if (!mBufferInfo.has_value()) {
237             return APEXCODEC_STATUS_BAD_STATE;
238         }
239         *outFlags = mBufferInfo->flags;
240         *outFrameIndex = mBufferInfo->frameIndex;
241         *outTimestampUs = mBufferInfo->timestampUs;
242         return APEXCODEC_STATUS_OK;
243     }
244 
getLinearBufferApexCodec_Buffer245     ApexCodec_Status getLinearBuffer(ApexCodec_LinearBuffer *outLinearBuffer) const {
246         if (mType != APEXCODEC_BUFFER_TYPE_LINEAR) {
247             return APEXCODEC_STATUS_BAD_STATE;
248         }
249         *outLinearBuffer = mLinearBuffer;
250         return APEXCODEC_STATUS_OK;
251     }
252 
getGraphicBufferApexCodec_Buffer253     ApexCodec_Status getGraphicBuffer(AHardwareBuffer **outGraphicBuffer) const {
254         if (mType != APEXCODEC_BUFFER_TYPE_GRAPHIC) {
255             return APEXCODEC_STATUS_BAD_STATE;
256         }
257         *outGraphicBuffer = mGraphicBuffer;
258         return APEXCODEC_STATUS_OK;
259     }
260 
getConfigUpdatesApexCodec_Buffer261     ApexCodec_Status getConfigUpdates(
262             ApexCodec_LinearBuffer *outConfigUpdates,
263             bool *outOwnedByClient) const {
264         if (!mConfigUpdates.has_value()) {
265             return APEXCODEC_STATUS_NOT_FOUND;
266         }
267         *outConfigUpdates = mConfigUpdates.value();
268         *outOwnedByClient = mOwnedConfigUpdates.has_value();
269         return APEXCODEC_STATUS_OK;
270     }
271 
setOwnedConfigUpdatesApexCodec_Buffer272     void setOwnedConfigUpdates(std::vector<uint8_t> &&configUpdates) {
273         mOwnedConfigUpdates = std::move(configUpdates);
274         mConfigUpdates.emplace(
275                 ApexCodec_LinearBuffer{ configUpdates.data(), configUpdates.size() });
276     }
277 
278 private:
279     struct BufferInfo {
280         ApexCodec_BufferFlags flags;
281         uint64_t frameIndex;
282         uint64_t timestampUs;
283     };
284 
285     ApexCodec_BufferType mType;
286     std::optional<BufferInfo> mBufferInfo;
287     ApexCodec_LinearBuffer mLinearBuffer;
288     AHardwareBuffer *mGraphicBuffer;
289     std::optional<ApexCodec_LinearBuffer> mConfigUpdates;
290     std::optional<std::vector<uint8_t>> mOwnedConfigUpdates;
291 };
292 
ApexCodec_Buffer_create()293 ApexCodec_Buffer *ApexCodec_Buffer_create() {
294     return new ApexCodec_Buffer;
295 }
296 
ApexCodec_Buffer_destroy(ApexCodec_Buffer * buffer)297 void ApexCodec_Buffer_destroy(ApexCodec_Buffer *buffer) {
298     delete buffer;
299 }
300 
ApexCodec_Buffer_clear(ApexCodec_Buffer * buffer)301 void ApexCodec_Buffer_clear(ApexCodec_Buffer *buffer) {
302     if (buffer == nullptr) {
303         return;
304     }
305     buffer->clear();
306 }
307 
ApexCodec_Buffer_getType(ApexCodec_Buffer * buffer)308 ApexCodec_BufferType ApexCodec_Buffer_getType(ApexCodec_Buffer *buffer) {
309     if (buffer == nullptr) {
310         return APEXCODEC_BUFFER_TYPE_EMPTY;
311     }
312     return buffer->getType();
313 }
314 
ApexCodec_Buffer_setBufferInfo(ApexCodec_Buffer * buffer,ApexCodec_BufferFlags flags,uint64_t frameIndex,uint64_t timestampUs)315 void ApexCodec_Buffer_setBufferInfo(
316         ApexCodec_Buffer *buffer,
317         ApexCodec_BufferFlags flags,
318         uint64_t frameIndex,
319         uint64_t timestampUs) {
320     if (buffer == nullptr) {
321         return;
322     }
323     buffer->setBufferInfo(flags, frameIndex, timestampUs);
324 }
325 
ApexCodec_Buffer_setLinearBuffer(ApexCodec_Buffer * buffer,const ApexCodec_LinearBuffer * linearBuffer)326 ApexCodec_Status ApexCodec_Buffer_setLinearBuffer(
327         ApexCodec_Buffer *buffer,
328         const ApexCodec_LinearBuffer *linearBuffer) {
329     if (buffer == nullptr) {
330         return APEXCODEC_STATUS_BAD_VALUE;
331     }
332     return buffer->setLinearBuffer(linearBuffer);
333 }
334 
ApexCodec_Buffer_setGraphicBuffer(ApexCodec_Buffer * buffer,AHardwareBuffer * graphicBuffer)335 ApexCodec_Status ApexCodec_Buffer_setGraphicBuffer(
336         ApexCodec_Buffer *buffer,
337         AHardwareBuffer *graphicBuffer) {
338     if (buffer == nullptr) {
339         return APEXCODEC_STATUS_BAD_VALUE;
340     }
341     return buffer->setGraphicBuffer(graphicBuffer);
342 }
343 
ApexCodec_Buffer_setConfigUpdates(ApexCodec_Buffer * buffer,const ApexCodec_LinearBuffer * configUpdates)344 ApexCodec_Status ApexCodec_Buffer_setConfigUpdates(
345         ApexCodec_Buffer *buffer,
346         const ApexCodec_LinearBuffer *configUpdates) {
347     if (buffer == nullptr) {
348         return APEXCODEC_STATUS_BAD_VALUE;
349     }
350     return buffer->setConfigUpdates(configUpdates);
351 }
352 
ApexCodec_Buffer_getBufferInfo(ApexCodec_Buffer * buffer,ApexCodec_BufferFlags * outFlags,uint64_t * outFrameIndex,uint64_t * outTimestampUs)353 ApexCodec_Status ApexCodec_Buffer_getBufferInfo(
354         ApexCodec_Buffer *buffer,
355         ApexCodec_BufferFlags *outFlags,
356         uint64_t *outFrameIndex,
357         uint64_t *outTimestampUs) {
358     if (buffer == nullptr) {
359         return APEXCODEC_STATUS_BAD_VALUE;
360     }
361     return buffer->getBufferInfo(outFlags, outFrameIndex, outTimestampUs);
362 }
363 
ApexCodec_Buffer_getLinearBuffer(ApexCodec_Buffer * buffer,ApexCodec_LinearBuffer * outLinearBuffer)364 ApexCodec_Status ApexCodec_Buffer_getLinearBuffer(
365         ApexCodec_Buffer *buffer,
366         ApexCodec_LinearBuffer *outLinearBuffer) {
367     if (buffer == nullptr) {
368         return APEXCODEC_STATUS_BAD_VALUE;
369     }
370     return buffer->getLinearBuffer(outLinearBuffer);
371 }
372 
ApexCodec_Buffer_getGraphicBuffer(ApexCodec_Buffer * buffer,AHardwareBuffer ** outGraphicBuffer)373 ApexCodec_Status ApexCodec_Buffer_getGraphicBuffer(
374         ApexCodec_Buffer *buffer,
375         AHardwareBuffer **outGraphicBuffer) {
376     if (buffer == nullptr) {
377         return APEXCODEC_STATUS_BAD_VALUE;
378     }
379     return buffer->getGraphicBuffer(outGraphicBuffer);
380 }
381 
ApexCodec_Buffer_getConfigUpdates(ApexCodec_Buffer * buffer,ApexCodec_LinearBuffer * outConfigUpdates,bool * outOwnedByClient)382 ApexCodec_Status ApexCodec_Buffer_getConfigUpdates(
383         ApexCodec_Buffer *buffer,
384         ApexCodec_LinearBuffer *outConfigUpdates,
385         bool *outOwnedByClient) {
386     if (buffer == nullptr) {
387         return APEXCODEC_STATUS_BAD_VALUE;
388     }
389     return buffer->getConfigUpdates(outConfigUpdates, outOwnedByClient);
390 }
391 
392 struct ApexCodec_SupportedValues {
393 public:
ApexCodec_SupportedValuesApexCodec_SupportedValues394     ApexCodec_SupportedValues(
395             const C2FieldSupportedValues &supportedValues,
396             const C2Value::type_t &numberType) {
397         mType = (ApexCodec_SupportedValuesType)supportedValues.type;
398         mNumberType = (ApexCodec_SupportedValuesNumberType)numberType;
399         switch (supportedValues.type) {
400             case C2FieldSupportedValues::RANGE: {
401                 mValues.insert(mValues.end(), 5, ApexCodec_Value{});
402                 ToApexCodecValue(supportedValues.range.min,   numberType, &mValues[0]);
403                 ToApexCodecValue(supportedValues.range.max,   numberType, &mValues[1]);
404                 ToApexCodecValue(supportedValues.range.step,  numberType, &mValues[2]);
405                 ToApexCodecValue(supportedValues.range.num,   numberType, &mValues[3]);
406                 ToApexCodecValue(supportedValues.range.denom, numberType, &mValues[4]);
407                 break;
408             }
409             case C2FieldSupportedValues::VALUES:
410             case C2FieldSupportedValues::FLAGS: {
411                 for (size_t i = 0; i < supportedValues.values.size(); ++i) {
412                     mValues.emplace_back();
413                     ToApexCodecValue(supportedValues.values[i], numberType, &mValues[i]);
414                 }
415                 break;
416             }
417             default:
418                 // Unrecognized type; initialize as empty.
419                 mType = APEXCODEC_SUPPORTED_VALUES_EMPTY;
420                 break;
421         }
422     }
423 
~ApexCodec_SupportedValuesApexCodec_SupportedValues424     ~ApexCodec_SupportedValues() {
425     }
426 
getTypeAndValuesApexCodec_SupportedValues427     ApexCodec_Status getTypeAndValues(
428             ApexCodec_SupportedValuesType *type,
429             ApexCodec_SupportedValuesNumberType *numberType,
430             ApexCodec_Value **values,
431             uint32_t *numValues) {
432         if (type == nullptr) {
433             return APEXCODEC_STATUS_BAD_VALUE;
434         }
435         if (numberType == nullptr) {
436             return APEXCODEC_STATUS_BAD_VALUE;
437         }
438         if (values == nullptr) {
439             return APEXCODEC_STATUS_BAD_VALUE;
440         }
441         if (numValues == nullptr) {
442             return APEXCODEC_STATUS_BAD_VALUE;
443         }
444         *type = mType;
445         *numberType = mNumberType;
446         switch (mType) {
447             case APEXCODEC_SUPPORTED_VALUES_EMPTY: {
448                 *values = nullptr;
449                 *numValues = 0;
450                 break;
451             }
452             case APEXCODEC_SUPPORTED_VALUES_RANGE:
453             case APEXCODEC_SUPPORTED_VALUES_VALUES:
454             case APEXCODEC_SUPPORTED_VALUES_FLAGS: {
455                 if (mValues.empty()) {
456                     return APEXCODEC_STATUS_BAD_STATE;
457                 }
458                 *values = mValues.data();
459                 *numValues = mValues.size();
460                 break;
461             }
462             default:
463                 return APEXCODEC_STATUS_BAD_STATE;
464         }
465         return APEXCODEC_STATUS_OK;
466     }
467 
ToApexCodecValueApexCodec_SupportedValues468     static bool ToApexCodecValue(
469             const C2Value::Primitive &value,
470             const C2Value::type_t &type,
471             ApexCodec_Value *outValue) {
472         switch (type) {
473             case C2Value::NO_INIT:
474                 return false;
475             case C2Value::INT32:
476                 outValue->i32 = value.i32;
477                 return true;
478             case C2Value::UINT32:
479                 outValue->u32 = value.u32;
480                 return true;
481             case C2Value::INT64:
482                 outValue->i64 = value.i64;
483                 return true;
484             case C2Value::UINT64:
485                 outValue->u64 = value.u64;
486                 return true;
487             case C2Value::FLOAT:
488                 outValue->f = value.fp;
489                 return true;
490             default:
491                 return false;
492         }
493     }
494 
GetFieldTypeApexCodec_SupportedValues495     static C2Value::type_t GetFieldType(
496             const std::shared_ptr<C2ParamReflector> &reflector,
497             const C2ParamField& field) {
498         std::unique_ptr<C2StructDescriptor> desc = reflector->describe(
499                 _C2ParamInspector::GetIndex(field));
500 
501         for (const C2FieldDescriptor &fieldDesc : *desc) {
502             if (_C2ParamInspector::GetOffset(fieldDesc) == _C2ParamInspector::GetOffset(field)) {
503                 if (_C2ParamInspector::GetSize(fieldDesc) != _C2ParamInspector::GetSize(field)) {
504                     // Size doesn't match.
505                     return C2Value::NO_INIT;
506                 }
507                 switch (fieldDesc.type()) {
508                     case C2FieldDescriptor::INT32:
509                     case C2FieldDescriptor::UINT32:
510                     case C2FieldDescriptor::INT64:
511                     case C2FieldDescriptor::UINT64:
512                     case C2FieldDescriptor::FLOAT:
513                         return (C2Value::type_t)fieldDesc.type();
514                     default:
515                         // Unrecognized type.
516                         return C2Value::NO_INIT;
517                 }
518             }
519         }
520         return C2Value::NO_INIT;
521     }
522 
523 private:
524     ApexCodec_SupportedValuesType mType;
525     ApexCodec_SupportedValuesNumberType mNumberType;
526     std::vector<ApexCodec_Value> mValues;
527 };
528 
ApexCodec_SupportedValues_getTypeAndValues(ApexCodec_SupportedValues * supportedValues,ApexCodec_SupportedValuesType * type,ApexCodec_SupportedValuesNumberType * numberType,ApexCodec_Value ** values,uint32_t * numValues)529 ApexCodec_Status ApexCodec_SupportedValues_getTypeAndValues(
530         ApexCodec_SupportedValues *supportedValues,
531         ApexCodec_SupportedValuesType *type,
532         ApexCodec_SupportedValuesNumberType *numberType,
533         ApexCodec_Value **values,
534         uint32_t *numValues) {
535     if (supportedValues == nullptr) {
536         return APEXCODEC_STATUS_BAD_VALUE;
537     }
538     return supportedValues->getTypeAndValues(type, numberType, values, numValues);
539 }
540 
ApexCodec_SupportedValues_destroy(ApexCodec_SupportedValues * values)541 void ApexCodec_SupportedValues_destroy(ApexCodec_SupportedValues *values) {
542     delete values;
543 }
544 
545 struct ApexCodec_SettingResults {
546 public:
ApexCodec_SettingResultsApexCodec_SettingResults547     explicit ApexCodec_SettingResults(
548             const std::shared_ptr<C2ParamReflector> &reflector,
549             const std::vector<C2SettingResult> &results) : mReflector(reflector) {
550         for (const C2SettingResult &c2Result : results) {
551             mResults.emplace_back();
552             Entry &entry = mResults.back();
553             entry.failure = (ApexCodec_SettingResultFailure)c2Result.failure;
554             entry.field.index = _C2ParamInspector::GetIndex(c2Result.field.paramOrField);
555             entry.field.offset = _C2ParamInspector::GetOffset(c2Result.field.paramOrField);
556             entry.field.size = _C2ParamInspector::GetSize(c2Result.field.paramOrField);
557             if (c2Result.field.values) {
558                 entry.fieldValues = std::make_unique<ApexCodec_SupportedValues>(
559                         *c2Result.field.values,
560                         ApexCodec_SupportedValues::GetFieldType(mReflector,
561                                                                 c2Result.field.paramOrField));
562                 entry.field.values = entry.fieldValues.get();
563             } else {
564                 entry.field.values = nullptr;
565             }
566             for (const C2ParamFieldValues &c2Conflict : c2Result.conflicts) {
567                 entry.conflicts.emplace_back();
568                 ApexCodec_ParamFieldValues &conflict = entry.conflicts.back();
569                 conflict.index = _C2ParamInspector::GetIndex(c2Conflict.paramOrField);
570                 conflict.offset = _C2ParamInspector::GetOffset(c2Conflict.paramOrField);
571                 conflict.size = _C2ParamInspector::GetSize(c2Conflict.paramOrField);
572                 if (c2Conflict.values) {
573                     entry.conflictValues.emplace_back(std::make_unique<ApexCodec_SupportedValues>(
574                             *c2Conflict.values,
575                             ApexCodec_SupportedValues::GetFieldType(mReflector,
576                                                                     c2Conflict.paramOrField)));
577                     conflict.values = entry.conflictValues.back().get();
578                 } else {
579                     conflict.values = nullptr;
580                 }
581             }
582         }
583     }
584 
~ApexCodec_SettingResultsApexCodec_SettingResults585     ~ApexCodec_SettingResults() {
586     }
587 
getResultAtIndexApexCodec_SettingResults588     ApexCodec_Status getResultAtIndex(
589             size_t index,
590             ApexCodec_SettingResultFailure *failure,
591             ApexCodec_ParamFieldValues *field,
592             ApexCodec_ParamFieldValues **conflicts,
593             size_t *numConflicts) {
594         if (failure == nullptr) {
595             return APEXCODEC_STATUS_BAD_VALUE;
596         }
597         if (field == nullptr) {
598             return APEXCODEC_STATUS_BAD_VALUE;
599         }
600         if (conflicts == nullptr) {
601             return APEXCODEC_STATUS_BAD_VALUE;
602         }
603         if (numConflicts == nullptr) {
604             return APEXCODEC_STATUS_BAD_VALUE;
605         }
606         if (index >= mResults.size()) {
607             return APEXCODEC_STATUS_NOT_FOUND;
608         }
609         *failure = mResults[index].failure;
610         *field = mResults[index].field;
611         *conflicts = mResults[index].conflicts.data();
612         *numConflicts = mResults[index].conflicts.size();
613         return APEXCODEC_STATUS_OK;
614     }
615 private:
616     std::shared_ptr<C2ParamReflector> mReflector;
617     struct Entry {
618         ApexCodec_SettingResultFailure failure;
619         ApexCodec_ParamFieldValues field;
620         std::vector<ApexCodec_ParamFieldValues> conflicts;
621         std::unique_ptr<ApexCodec_SupportedValues> fieldValues;
622         std::vector<std::unique_ptr<ApexCodec_SupportedValues>> conflictValues;
623     };
624     std::vector<Entry> mResults;
625 };
626 
ApexCodec_SettingResults_getResultAtIndex(ApexCodec_SettingResults * results,size_t index,ApexCodec_SettingResultFailure * failure,ApexCodec_ParamFieldValues * field,ApexCodec_ParamFieldValues ** conflicts,size_t * numConflicts)627 ApexCodec_Status ApexCodec_SettingResults_getResultAtIndex(
628         ApexCodec_SettingResults *results,
629         size_t index,
630         ApexCodec_SettingResultFailure *failure,
631         ApexCodec_ParamFieldValues *field,
632         ApexCodec_ParamFieldValues **conflicts,
633         size_t *numConflicts) {
634     if (results == nullptr) {
635         return APEXCODEC_STATUS_BAD_VALUE;
636     }
637     return results->getResultAtIndex(index, failure, field, conflicts, numConflicts);
638 }
639 
ApexCodec_SettingResults_destroy(ApexCodec_SettingResults * results)640 void ApexCodec_SettingResults_destroy(ApexCodec_SettingResults *results) {
641     delete results;
642 }
643 
ApexCodec_Component_process(ApexCodec_Component * comp,const ApexCodec_Buffer * input,ApexCodec_Buffer * output,size_t * consumed,size_t * produced)644 ApexCodec_Status ApexCodec_Component_process(
645         ApexCodec_Component *comp,
646         const ApexCodec_Buffer *input,
647         ApexCodec_Buffer *output,
648         size_t *consumed,
649         size_t *produced) {
650     return APEXCODEC_STATUS_OMITTED;
651 }
652 
ApexCodec_Configurable_config(ApexCodec_Configurable * comp,ApexCodec_LinearBuffer * config,ApexCodec_SettingResults ** results)653 ApexCodec_Status ApexCodec_Configurable_config(
654         ApexCodec_Configurable *comp,
655         ApexCodec_LinearBuffer *config,
656         ApexCodec_SettingResults **results) {
657     return APEXCODEC_STATUS_OMITTED;
658 }
659 
ApexCodec_Configurable_query(ApexCodec_Configurable * comp,uint32_t indices[],size_t numIndices,ApexCodec_LinearBuffer * config,size_t * writtenOrRequired)660 ApexCodec_Status ApexCodec_Configurable_query(
661         ApexCodec_Configurable *comp,
662         uint32_t indices[],
663         size_t numIndices,
664         ApexCodec_LinearBuffer *config,
665         size_t *writtenOrRequired) {
666     return APEXCODEC_STATUS_OMITTED;
667 }
668 
669 struct ApexCodec_ParamDescriptors {
670 public:
ApexCodec_ParamDescriptorsApexCodec_ParamDescriptors671     explicit ApexCodec_ParamDescriptors(
672             const std::vector<std::shared_ptr<C2ParamDescriptor>> &paramDescriptors) {
673         for (const std::shared_ptr<C2ParamDescriptor> &c2Descriptor : paramDescriptors) {
674             if (!c2Descriptor) {
675                 continue;
676             }
677             uint32_t index = c2Descriptor->index();
678             Entry &entry = mDescriptors[index];
679             entry.index = index;
680             entry.attr = (ApexCodec_ParamAttribute)_C2ParamInspector::GetAttrib(*c2Descriptor);
681             entry.name = c2Descriptor->name();
682             for (const C2Param::Index &dependency : c2Descriptor->dependencies()) {
683                 entry.dependencies.emplace_back((uint32_t)dependency);
684             }
685             mIndices.push_back(entry.index);
686         }
687     }
688 
~ApexCodec_ParamDescriptorsApexCodec_ParamDescriptors689     ~ApexCodec_ParamDescriptors() {
690     }
691 
getIndicesApexCodec_ParamDescriptors692     ApexCodec_Status getIndices(uint32_t **indices, size_t *numIndices) {
693         if (indices == nullptr) {
694             return APEXCODEC_STATUS_BAD_VALUE;
695         }
696         if (numIndices == nullptr) {
697             return APEXCODEC_STATUS_BAD_VALUE;
698         }
699         *indices = mIndices.data();
700         *numIndices = mIndices.size();
701         return APEXCODEC_STATUS_OK;
702     }
703 
getDescriptorApexCodec_ParamDescriptors704     ApexCodec_Status getDescriptor(
705             uint32_t index,
706             ApexCodec_ParamAttribute *attr,
707             const char **name,
708             uint32_t **dependencies,
709             size_t *numDependencies) {
710         if (attr == nullptr) {
711             return APEXCODEC_STATUS_BAD_VALUE;
712         }
713         if (name == nullptr) {
714             return APEXCODEC_STATUS_BAD_VALUE;
715         }
716         if (dependencies == nullptr) {
717             return APEXCODEC_STATUS_BAD_VALUE;
718         }
719         if (numDependencies == nullptr) {
720             return APEXCODEC_STATUS_BAD_VALUE;
721         }
722         auto it = mDescriptors.find(index);
723         if (it == mDescriptors.end()) {
724             return APEXCODEC_STATUS_BAD_VALUE;
725         }
726         const Entry &entry = it->second;
727         *attr = entry.attr;
728         *name = entry.name.c_str();
729         *dependencies = const_cast<uint32_t *>(entry.dependencies.data());
730         *numDependencies = entry.dependencies.size();
731         return APEXCODEC_STATUS_OK;
732     }
733 
734 private:
735     struct Entry {
736         uint32_t index;
737         ApexCodec_ParamAttribute attr;
738         C2String name;
739         std::vector<uint32_t> dependencies;
740     };
741     std::map<uint32_t, Entry> mDescriptors;
742     std::vector<uint32_t> mIndices;
743 };
744 
ApexCodec_ParamDescriptors_getIndices(ApexCodec_ParamDescriptors * descriptors,uint32_t ** indices,size_t * numIndices)745 ApexCodec_Status ApexCodec_ParamDescriptors_getIndices(
746         ApexCodec_ParamDescriptors *descriptors,
747         uint32_t **indices,
748         size_t *numIndices) {
749     if (descriptors == nullptr) {
750         return APEXCODEC_STATUS_BAD_VALUE;
751     }
752     return descriptors->getIndices(indices, numIndices);
753 }
754 
ApexCodec_ParamDescriptors_getDescriptor(ApexCodec_ParamDescriptors * descriptors,uint32_t index,ApexCodec_ParamAttribute * attr,const char ** name,uint32_t ** dependencies,size_t * numDependencies)755 ApexCodec_Status ApexCodec_ParamDescriptors_getDescriptor(
756         ApexCodec_ParamDescriptors *descriptors,
757         uint32_t index,
758         ApexCodec_ParamAttribute *attr,
759         const char **name,
760         uint32_t **dependencies,
761         size_t *numDependencies) {
762     if (descriptors == nullptr) {
763         return APEXCODEC_STATUS_BAD_VALUE;
764     }
765     return descriptors->getDescriptor(index, attr, name, dependencies, numDependencies);
766 }
767 
ApexCodec_ParamDescriptors_destroy(ApexCodec_ParamDescriptors * descriptors)768 void ApexCodec_ParamDescriptors_destroy(ApexCodec_ParamDescriptors *descriptors) {
769     delete descriptors;
770 }
771 
ApexCodec_Configurable_querySupportedParams(ApexCodec_Configurable * comp,ApexCodec_ParamDescriptors ** descriptors)772 ApexCodec_Status ApexCodec_Configurable_querySupportedParams(
773         ApexCodec_Configurable *comp,
774         ApexCodec_ParamDescriptors **descriptors) {
775     return APEXCODEC_STATUS_OMITTED;
776 }
777 
ApexCodec_Configurable_querySupportedValues(ApexCodec_Configurable * comp,ApexCodec_SupportedValuesQuery * queries,size_t numQueries)778 ApexCodec_Status ApexCodec_Configurable_querySupportedValues(
779         ApexCodec_Configurable *comp,
780         ApexCodec_SupportedValuesQuery *queries,
781         size_t numQueries) {
782     return APEXCODEC_STATUS_OMITTED;
783 }
784 
785 #pragma clang diagnostic pop