• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 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-FilterWrapper"
19 #include <android-base/logging.h>
20 
21 #include <set>
22 
23 #include <dlfcn.h>
24 
25 #include <C2Config.h>
26 #include <C2Debug.h>
27 #include <C2ParamInternal.h>
28 
29 #include <codec2/hidl/plugin/FilterPlugin.h>
30 
31 #include <FilterWrapper.h>
32 
33 namespace android {
34 
35 namespace {
36 
37 // Indices that the last filter in the chain should consume.
38 static constexpr uint32_t kTypesForLastFilter[] = {
39     // In case we have an output surface, we want to use the block pool
40     // backed by the output surface for the output buffer going to the client.
41     C2PortBlockPoolsTuning::output::PARAM_TYPE,
42 };
43 
44 class WrappedDecoderInterface : public C2ComponentInterface {
45 public:
WrappedDecoderInterface(std::shared_ptr<C2ComponentInterface> intf,std::vector<FilterWrapper::Component> && filters,std::weak_ptr<FilterWrapper> filterWrapper)46     WrappedDecoderInterface(
47             std::shared_ptr<C2ComponentInterface> intf,
48             std::vector<FilterWrapper::Component> &&filters,
49             std::weak_ptr<FilterWrapper> filterWrapper)
50         : mIntf(intf), mFilterWrapper(filterWrapper) {
51         takeFilters(std::move(filters));
52         for (size_t i = 0; i < mFilters.size(); ++i) {
53             mControlParamTypes.insert(
54                     mFilters[i].desc.controlParams.begin(),
55                     mFilters[i].desc.controlParams.end());
56         }
57     }
58 
59     ~WrappedDecoderInterface() override = default;
60 
takeFilters(std::vector<FilterWrapper::Component> && filters)61     void takeFilters(std::vector<FilterWrapper::Component> &&filters) {
62         std::unique_lock lock(mMutex);
63         std::vector<std::unique_ptr<C2Param>> lastFilterParams;
64         if (!mFilters.empty()) {
65             std::vector<C2Param::Index> indices;
66             std::vector<std::shared_ptr<C2ParamDescriptor>> paramDescs;
67             c2_status_t err = mFilters.back().intf->querySupportedParams_nb(&paramDescs);
68             if (err != C2_OK) {
69                 LOG(WARNING) << "WrappedDecoderInterface: " << mFilters.back().traits.name
70                         << " returned error for querySupportedParams_nb; err=" << err;
71                 paramDescs.clear();
72             }
73             for (const std::shared_ptr<C2ParamDescriptor> &paramDesc : paramDescs) {
74                 C2Param::Index index = paramDesc->index();
75                 if (std::count(
76                             std::begin(kTypesForLastFilter),
77                             std::end(kTypesForLastFilter),
78                             index.type()) != 0) {
79                     if (index.forStream()) {
80                         // querySupportedParams does not return per-stream params.
81                         // We only support stream-0 for now.
82                         index = index.withStream(0u);
83                     }
84                     indices.push_back(index);
85                 }
86             }
87             if (!indices.empty()) {
88                 mFilters.back().intf->query_vb({}, indices, C2_MAY_BLOCK, &lastFilterParams);
89             }
90         }
91 
92         // TODO: documentation
93         mFilters = std::move(filters);
94         mTypeToIndexForQuery.clear();
95         mTypeToIndexForConfig.clear();
96         for (size_t i = 0; i < mFilters.size(); ++i) {
97             if (i == 0) {
98                 transferParams_l(mIntf, mFilters[0].intf, C2_MAY_BLOCK);
99             } else {
100                 transferParams_l(mFilters[i - 1].intf, mFilters[i].intf, C2_MAY_BLOCK);
101             }
102             for (C2Param::Type type : mFilters[i].desc.controlParams) {
103                 mTypeToIndexForQuery[type.type()] = i;
104                 mTypeToIndexForConfig[type.type() & ~C2Param::CoreIndex::IS_REQUEST_FLAG] = i;
105             }
106             for (C2Param::Type type : mFilters[i].desc.affectedParams) {
107                 mTypeToIndexForQuery[type.type()] = i;
108             }
109         }
110         for (size_t i = mFilters.size(); i > 0; --i) {
111             if (i == 1) {
112                 backPropagateParams_l(mIntf, mFilters[0].intf, C2_MAY_BLOCK);
113             } else {
114                 backPropagateParams_l(mFilters[i - 2].intf, mFilters[i - 1].intf, C2_MAY_BLOCK);
115             }
116         }
117         if (!mFilters.empty()) {
118             for (uint32_t type : kTypesForLastFilter) {
119                 mTypeToIndexForQuery[type] = mFilters.size() - 1;
120                 mTypeToIndexForConfig[type & ~C2Param::CoreIndex::IS_REQUEST_FLAG] =
121                     mFilters.size() - 1;
122             }
123             if (!lastFilterParams.empty()) {
124                 std::vector<C2Param *> paramPtrs(lastFilterParams.size());
125                 std::transform(
126                         lastFilterParams.begin(),
127                         lastFilterParams.end(),
128                         paramPtrs.begin(),
129                         [](const std::unique_ptr<C2Param> &param) {
130                             return param.get();
131                         });
132                 std::vector<std::unique_ptr<C2SettingResult>> failures;
133                 mFilters.back().intf->config_vb(paramPtrs, C2_MAY_BLOCK, &failures);
134             }
135         }
136     }
137 
getName() const138     C2String getName() const override { return mIntf->getName(); }
139 
getId() const140     c2_node_id_t getId() const override { return mIntf->getId(); }
141 
query_vb(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,c2_blocking_t mayBlock,std::vector<std::unique_ptr<C2Param>> * const heapParams) const142     c2_status_t query_vb(
143             const std::vector<C2Param *> &stackParams,
144             const std::vector<C2Param::Index> &heapParamIndices,
145             c2_blocking_t mayBlock,
146             std::vector<std::unique_ptr<C2Param>>* const heapParams) const override {
147         std::unique_lock lock(mMutex);
148         std::list<C2Param *> stackParamsList(stackParams.size());
149         std::copy_n(stackParams.begin(), stackParams.size(), stackParamsList.begin());
150         heapParams->clear();
151         c2_status_t result = C2_OK;
152         // TODO: loop optimization
153         for (size_t i = 0; i < mFilters.size(); ++i) {
154             // Filter stack params according to mTypeToIndexForQuery
155             std::vector<C2Param *> stackParamsForFilter;
156             for (auto it = stackParamsList.begin(); it != stackParamsList.end(); ) {
157                 C2Param *param = *it;
158                 uint32_t type = param->type().type();
159                 auto it2 = mTypeToIndexForQuery.find(type);
160                 if (it2 == mTypeToIndexForQuery.end() || it2->second != i) {
161                     ++it;
162                     continue;
163                 }
164                 stackParamsForFilter.push_back(param);
165                 it = stackParamsList.erase(it);
166             }
167             // Filter heap params according to mTypeToIndexForQuery
168             std::vector<C2Param::Index> heapParamIndicesForFilter;
169             for (size_t j = 0; j < heapParamIndices.size(); ++j) {
170                 uint32_t type = heapParamIndices[j].type();
171                 auto it = mTypeToIndexForQuery.find(type);
172                 if (it == mTypeToIndexForQuery.end() || it->second != i) {
173                     continue;
174                 }
175                 heapParamIndicesForFilter.push_back(heapParamIndices[j]);
176             }
177             std::vector<std::unique_ptr<C2Param>> heapParamsForFilter;
178             const std::shared_ptr<C2ComponentInterface> &filter = mFilters[i].intf;
179             c2_status_t err = filter->query_vb(
180                     stackParamsForFilter, heapParamIndicesForFilter, mayBlock,
181                     &heapParamsForFilter);
182             if (err != C2_OK && err != C2_BAD_INDEX) {
183                 LOG(WARNING) << "WrappedDecoderInterface: " << filter->getName()
184                         << " returned error for query_vb; err=" << err;
185                 result = err;
186                 continue;
187             }
188             heapParams->insert(
189                     heapParams->end(),
190                     std::make_move_iterator(heapParamsForFilter.begin()),
191                     std::make_move_iterator(heapParamsForFilter.end()));
192         }
193 
194         std::vector<C2Param *> stackParamsForIntf;
195         for (C2Param *param : stackParamsList) {
196             if (mControlParamTypes.count(param->type()) != 0) {
197                 continue;
198             }
199             stackParamsForIntf.push_back(param);
200         }
201 
202         // Gather heap params that did not get queried from the filter interfaces above.
203         // These need to be queried from the decoder interface.
204         std::vector<C2Param::Index> heapParamIndicesForIntf;
205         for (size_t j = 0; j < heapParamIndices.size(); ++j) {
206             uint32_t type = heapParamIndices[j].type();
207             if (mTypeToIndexForQuery.find(type) != mTypeToIndexForQuery.end()) {
208                 continue;
209             }
210             if (mControlParamTypes.count(type) != 0) {
211                 continue;
212             }
213             heapParamIndicesForIntf.push_back(heapParamIndices[j]);
214         }
215 
216         std::vector<std::unique_ptr<C2Param>> heapParamsForIntf;
217         c2_status_t err = mIntf->query_vb(
218                 stackParamsForIntf, heapParamIndicesForIntf, mayBlock, &heapParamsForIntf);
219         if (err != C2_OK) {
220             LOG(err == C2_BAD_INDEX ? VERBOSE : WARNING)
221                     << "WrappedDecoderInterface: " << mIntf->getName()
222                     << " returned error for query_vb; err=" << err;
223             result = err;
224         }
225 
226         // TODO: params needs to preserve the order
227         heapParams->insert(
228                 heapParams->end(),
229                 std::make_move_iterator(heapParamsForIntf.begin()),
230                 std::make_move_iterator(heapParamsForIntf.end()));
231 
232         return result;
233     }
234 
config_vb(const std::vector<C2Param * > & params,c2_blocking_t mayBlock,std::vector<std::unique_ptr<C2SettingResult>> * const failures)235     c2_status_t config_vb(
236             const std::vector<C2Param *> &params,
237             c2_blocking_t mayBlock,
238             std::vector<std::unique_ptr<C2SettingResult>>* const failures) override {
239         std::unique_lock lock(mMutex);
240         c2_status_t result = C2_OK;
241         std::vector<C2Param *> paramsForIntf;
242         for (C2Param* param : params) {
243             auto it = mTypeToIndexForConfig.find(param->type().type());
244             if (it != mTypeToIndexForConfig.end()) {
245                 continue;
246             }
247             paramsForIntf.push_back(param);
248         }
249         c2_status_t err = mIntf->config_vb(paramsForIntf, mayBlock, failures);
250         if (err != C2_OK) {
251             LOG(err == C2_BAD_INDEX ? VERBOSE : WARNING)
252                     << "WrappedDecoderInterface: " << mIntf->getName()
253                     << " returned error for config_vb; err=" << err;
254             result = err;
255         }
256         for (size_t i = 0; i < mFilters.size(); ++i) {
257             if (i == 0) {
258                 transferParams_l(mIntf, mFilters[0].intf, mayBlock);
259             } else {
260                 transferParams_l(mFilters[i - 1].intf, mFilters[i].intf, mayBlock);
261             }
262             const std::shared_ptr<C2ComponentInterface> &filter = mFilters[i].intf;
263             std::vector<std::unique_ptr<C2SettingResult>> filterFailures;
264             std::vector<C2Param *> paramsForFilter;
265             for (C2Param* param : params) {
266                 auto it = mTypeToIndexForConfig.find(param->type().type());
267                 if (it == mTypeToIndexForConfig.end() || it->second != i) {
268                     continue;
269                 }
270                 paramsForFilter.push_back(param);
271             }
272             if (paramsForFilter.empty()) {
273                 continue;
274             }
275             c2_status_t err = filter->config_vb(paramsForFilter, mayBlock, &filterFailures);
276             if (err != C2_OK) {
277                 LOG(err == C2_BAD_INDEX ? VERBOSE : WARNING)
278                         << "WrappedDecoderInterface: " << filter->getName()
279                         << " returned error for config_vb; err=" << err;
280                 result = err;
281             }
282         }
283         for (size_t i = mFilters.size(); i > 0; --i) {
284             if (i == 1) {
285                 backPropagateParams_l(mIntf, mFilters[0].intf, mayBlock);
286             } else {
287                 backPropagateParams_l(mFilters[i - 2].intf, mFilters[i - 1].intf, mayBlock);
288             }
289         }
290 
291         return result;
292     }
293 
createTunnel_sm(c2_node_id_t)294     c2_status_t createTunnel_sm(c2_node_id_t) override { return C2_OMITTED; }
releaseTunnel_sm(c2_node_id_t)295     c2_status_t releaseTunnel_sm(c2_node_id_t) override { return C2_OMITTED; }
296 
querySupportedParams_nb(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const297     c2_status_t querySupportedParams_nb(
298             std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const override {
299         std::unique_lock lock(mMutex);
300         c2_status_t result = mIntf->querySupportedParams_nb(params);
301         if (result != C2_OK) {
302             LOG(WARNING) << "WrappedDecoderInterface: " << mIntf->getName()
303                     << " returned error for querySupportedParams_nb; err=" << result;
304             return result;
305         }
306         // TODO: optimization idea --- pre-compute at takeFilter().
307         for (const FilterWrapper::Component &filter : mFilters) {
308             std::vector<std::shared_ptr<C2ParamDescriptor>> filterParams;
309             c2_status_t err = filter.intf->querySupportedParams_nb(&filterParams);
310             if (err != C2_OK) {
311                 LOG(WARNING) << "WrappedDecoderInterface: " << filter.intf->getName()
312                         << " returned error for querySupportedParams_nb; err=" << result;
313                 result = err;
314                 continue;
315             }
316             for (const std::shared_ptr<C2ParamDescriptor> &paramDesc : filterParams) {
317                 if (std::count(
318                         filter.desc.controlParams.begin(),
319                         filter.desc.controlParams.end(),
320                         paramDesc->index().type()) == 0) {
321                     continue;
322                 }
323                 params->push_back(paramDesc);
324             }
325         }
326         return result;
327     }
328 
querySupportedValues_vb(std::vector<C2FieldSupportedValuesQuery> & fields,c2_blocking_t mayBlock) const329     c2_status_t querySupportedValues_vb(
330             std::vector<C2FieldSupportedValuesQuery> &fields,
331             c2_blocking_t mayBlock) const override {
332         std::unique_lock lock(mMutex);
333         c2_status_t result = mIntf->querySupportedValues_vb(fields, mayBlock);
334         if (result != C2_OK && result != C2_BAD_INDEX) {
335             LOG(WARNING) << "WrappedDecoderInterface: " << mIntf->getName()
336                     << " returned error for querySupportedParams_nb; err=" << result;
337             return result;
338         }
339         for (const FilterWrapper::Component &filter : mFilters) {
340             std::vector<C2FieldSupportedValuesQuery> filterFields;
341             std::vector<size_t> indices;
342             for (size_t i = 0; i < fields.size(); ++i) {
343                 const C2FieldSupportedValuesQuery &field = fields[i];
344                 uint32_t type = C2Param::Index(_C2ParamInspector::GetIndex(field.field())).type();
345                 if (std::count(
346                         filter.desc.controlParams.begin(),
347                         filter.desc.controlParams.end(),
348                         type) == 0) {
349                     continue;
350                 }
351                 filterFields.push_back(field);
352                 indices.push_back(i);
353             }
354             c2_status_t err = filter.intf->querySupportedValues_vb(filterFields, mayBlock);
355             if (err != C2_OK && err != C2_BAD_INDEX) {
356                 LOG(WARNING) << "WrappedDecoderInterface: " << filter.intf->getName()
357                         << " returned error for querySupportedParams_nb; err=" << result;
358                 result = err;
359                 continue;
360             }
361             for (size_t i = 0; i < filterFields.size(); ++i) {
362                 fields[indices[i]] = filterFields[i];
363             }
364         }
365         return result;
366     }
367 
368 private:
369     mutable std::mutex mMutex;
370     std::shared_ptr<C2ComponentInterface> mIntf;
371     std::vector<FilterWrapper::Component> mFilters;
372     std::weak_ptr<FilterWrapper> mFilterWrapper;
373     std::map<uint32_t, size_t> mTypeToIndexForQuery;
374     std::map<uint32_t, size_t> mTypeToIndexForConfig;
375     std::set<C2Param::Type> mControlParamTypes;
376 
transferParams_l(const std::shared_ptr<C2ComponentInterface> & curr,const std::shared_ptr<C2ComponentInterface> & next,c2_blocking_t mayBlock)377     c2_status_t transferParams_l(
378             const std::shared_ptr<C2ComponentInterface> &curr,
379             const std::shared_ptr<C2ComponentInterface> &next,
380             c2_blocking_t mayBlock) {
381         // NOTE: this implementation is preliminary --- it could change once
382         // we define what parameters needs to be propagated in component chaining.
383         std::vector<std::shared_ptr<C2ParamDescriptor>> paramDescs;
384         c2_status_t err = next->querySupportedParams_nb(&paramDescs);
385         if (err != C2_OK) {
386             LOG(DEBUG) << "WrappedDecoderInterface: " << next->getName()
387                     << " returned error for querySupportedParams_nb; err=" << err;
388             return err;
389         }
390         // Find supported input params from the next interface and flip direction
391         // so they become output params.
392         std::vector<C2Param::Index> indices;
393         for (const std::shared_ptr<C2ParamDescriptor> &paramDesc : paramDescs) {
394             C2Param::Index index = paramDesc->index();
395             if (!index.forInput() || paramDesc->isReadOnly()) {
396                 continue;
397             }
398             if (index.forStream()) {
399                 uint32_t stream = index.stream();
400                 index = index.withPort(true /* output */).withStream(stream);
401             } else {
402                 index = index.withPort(true /* output */);
403             }
404             indices.push_back(index);
405         }
406         // Query those output params from the current interface
407         std::vector<std::unique_ptr<C2Param>> heapParams;
408         err = curr->query_vb({}, indices, mayBlock, &heapParams);
409         if (err != C2_OK && err != C2_BAD_INDEX) {
410             LOG(DEBUG) << "WrappedDecoderInterface: " << curr->getName()
411                     << " returned error for query_vb; err=" << err;
412             return err;
413         }
414         // Flip the direction of the queried params, so they become input parameters.
415         // Configure the next interface with the params.
416         std::vector<C2Param *> configParams;
417         for (size_t i = 0; i < heapParams.size(); ++i) {
418             if (!heapParams[i]) {
419                 continue;
420             }
421             if (heapParams[i]->forStream()) {
422                 heapParams[i] = C2Param::CopyAsStream(
423                         *heapParams[i], false /* output */, heapParams[i]->stream());
424             } else {
425                 heapParams[i] = C2Param::CopyAsPort(*heapParams[i], false /* output */);
426             }
427             configParams.push_back(heapParams[i].get());
428         }
429         std::vector<std::unique_ptr<C2SettingResult>> failures;
430         err = next->config_vb(configParams, mayBlock, &failures);
431         if (err != C2_OK && err != C2_BAD_INDEX) {
432             LOG(DEBUG) << "WrappedDecoderInterface: " << next->getName()
433                     << " returned error for config_vb; err=" << err;
434             return err;
435         }
436         return C2_OK;
437     }
438 
backPropagateParams_l(const std::shared_ptr<C2ComponentInterface> & curr,const std::shared_ptr<C2ComponentInterface> & next,c2_blocking_t mayBlock)439     c2_status_t backPropagateParams_l(
440             const std::shared_ptr<C2ComponentInterface> &curr,
441             const std::shared_ptr<C2ComponentInterface> &next,
442             c2_blocking_t mayBlock) {
443         // NOTE: this implementation is preliminary --- it could change once
444         // we define what parameters needs to be propagated in component chaining.
445         std::shared_ptr<FilterWrapper> filterWrapper = mFilterWrapper.lock();
446         if (!filterWrapper) {
447             LOG(DEBUG) << "WrappedDecoderInterface: FilterWrapper not found";
448             return C2_OK;
449         }
450         if (!filterWrapper->isFilteringEnabled(next)) {
451             LOG(VERBOSE) << "WrappedDecoderInterface: filtering not enabled";
452             return C2_OK;
453         }
454         std::vector<std::unique_ptr<C2Param>> params;
455         c2_status_t err = filterWrapper->queryParamsForPreviousComponent(next, &params);
456         if (err != C2_OK) {
457             LOG(DEBUG) << "WrappedDecoderInterface: FilterWrapper returned error for "
458                 << "queryParamsForPreviousComponent; intf=" << next->getName() << " err=" << err;
459             return C2_OK;
460         }
461         std::vector<C2Param *> configParams;
462         for (size_t i = 0; i < params.size(); ++i) {
463             if (!params[i]) {
464                 continue;
465             }
466             configParams.push_back(params[i].get());
467         }
468         std::vector<std::unique_ptr<C2SettingResult>> failures;
469         curr->config_vb(configParams, mayBlock, &failures);
470         if (err != C2_OK && err != C2_BAD_INDEX) {
471             LOG(DEBUG) << "WrappedDecoderInterface: " << next->getName()
472                     << " returned error for config_vb; err=" << err;
473             return err;
474         }
475         return C2_OK;
476     }
477 };
478 
479 class WrappedDecoder : public C2Component, public std::enable_shared_from_this<WrappedDecoder> {
480 public:
WrappedDecoder(std::shared_ptr<C2Component> comp,std::vector<FilterWrapper::Component> && filters,std::weak_ptr<FilterWrapper> filterWrapper)481     WrappedDecoder(
482             std::shared_ptr<C2Component> comp,
483             std::vector<FilterWrapper::Component> &&filters,
484             std::weak_ptr<FilterWrapper> filterWrapper)
485         : mComp(comp), mFilters(std::move(filters)), mFilterWrapper(filterWrapper) {
486         std::vector<FilterWrapper::Component> filtersDup(mFilters);
487         mIntf = std::make_shared<WrappedDecoderInterface>(
488                 comp->intf(), std::move(filtersDup), filterWrapper);
489     }
490 
491     ~WrappedDecoder() override = default;
492 
intf()493     std::shared_ptr<C2ComponentInterface> intf() override { return mIntf; }
494 
setListener_vb(const std::shared_ptr<Listener> & listener,c2_blocking_t mayBlock)495     c2_status_t setListener_vb(
496             const std::shared_ptr<Listener> &listener, c2_blocking_t mayBlock) override {
497         if (listener) {
498             setListenerInternal(mFilters, listener, mayBlock);
499         } else {
500             mComp->setListener_vb(nullptr, mayBlock);
501             for (FilterWrapper::Component &filter : mFilters) {
502                 filter.comp->setListener_vb(nullptr, mayBlock);
503             }
504         }
505         mListener = listener;
506         return C2_OK;
507     }
508 
queue_nb(std::list<std::unique_ptr<C2Work>> * const items)509     c2_status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override {
510         return mComp->queue_nb(items);
511     }
512 
announce_nb(const std::vector<C2WorkOutline> &)513     c2_status_t announce_nb(const std::vector<C2WorkOutline> &) override {
514         return C2_OMITTED;
515     }
516 
flush_sm(flush_mode_t mode,std::list<std::unique_ptr<C2Work>> * const flushedWork)517     c2_status_t flush_sm(
518             flush_mode_t mode, std::list<std::unique_ptr<C2Work>>* const flushedWork) override {
519         c2_status_t result = mComp->flush_sm(mode, flushedWork);
520         std::list<std::unique_ptr<C2Work>> filterFlushedWork;
521         for (FilterWrapper::Component filter : mRunningFilters) {
522             c2_status_t err = filter.comp->flush_sm(mode, &filterFlushedWork);
523             if (err != C2_OK) {
524                 result = err;
525             }
526             flushedWork->splice(flushedWork->end(), filterFlushedWork);
527         }
528         return result;
529     }
530 
drain_nb(drain_mode_t mode)531     c2_status_t drain_nb(drain_mode_t mode) override {
532         // TODO: simplify using comp->drain_nb(mode)
533         switch (mode) {
534         case DRAIN_COMPONENT_WITH_EOS: {
535             std::unique_ptr<C2Work> eosWork{new C2Work};
536             eosWork->input.flags = C2FrameData::FLAG_END_OF_STREAM;
537             eosWork->worklets.push_back(std::make_unique<C2Worklet>());
538             std::list<std::unique_ptr<C2Work>> items;
539             items.push_back(std::move(eosWork));
540             mComp->queue_nb(&items);
541             return C2_OK;
542         }
543         case DRAIN_COMPONENT_NO_EOS:
544         case DRAIN_CHAIN:
545         default:
546             return C2_BAD_VALUE;
547         }
548     }
549 
start()550     c2_status_t start() override {
551         std::vector<FilterWrapper::Component> filters;
552         if (std::shared_ptr<FilterWrapper> filterWrapper = mFilterWrapper.lock()) {
553             // Let's check if we have filters that we can skip
554             for (FilterWrapper::Component &filter : mFilters) {
555                 if (!filterWrapper->isFilteringEnabled(filter.intf)) {
556                     LOG(VERBOSE) << "filtering disabled for " << filter.traits.name;
557                     continue;
558                 }
559                 LOG(VERBOSE) << "filtering enabled for " << filter.traits.name;
560                 filters.push_back(filter);
561             }
562             if (filters.size() < mFilters.size()) {
563                 LOG(VERBOSE) << (mFilters.size() - filters.size()) << " filter(s) skipped";
564                 setListenerInternal(filters, mListener, C2_MAY_BLOCK);
565                 std::vector filtersCopy(filters);
566                 mIntf->takeFilters(std::move(filtersCopy));
567             }
568         }
569 
570         c2_status_t err = mComp->start();
571         if (err != C2_OK) {
572             return err;
573         }
574         for (FilterWrapper::Component &filter : filters) {
575             c2_status_t err = filter.comp->start();
576             if (err != C2_OK) {
577                 // Previous components are already started successfully;
578                 // we ended up in an incoherent state.
579                 return C2_CORRUPTED;
580             }
581         }
582         mRunningFilters = std::move(filters);
583         return C2_OK;
584     }
585 
stop()586     c2_status_t stop() override {
587         c2_status_t err = mComp->stop();
588         if (err != C2_OK) {
589             return err;
590         }
591         for (FilterWrapper::Component filter : mRunningFilters) {
592             c2_status_t err = filter.comp->stop();
593             if (err != C2_OK) {
594                 // Previous components are already stopped successfully;
595                 // we ended up in an incoherent state.
596                 return C2_CORRUPTED;
597             }
598         }
599         mRunningFilters.clear();
600         return C2_OK;
601     }
602 
reset()603     c2_status_t reset() override {
604         c2_status_t result = mComp->reset();
605         if (result != C2_OK) {
606             result = C2_CORRUPTED;
607         }
608         for (FilterWrapper::Component filter : mFilters) {
609             c2_status_t err = filter.comp->reset();
610             if (err != C2_OK) {
611                 // Previous components are already reset successfully;
612                 // we ended up in an incoherent state.
613                 result = C2_CORRUPTED;
614                 // continue for the rest of the chain
615             }
616         }
617         mRunningFilters.clear();
618         std::vector<FilterWrapper::Component> filters(mFilters);
619         mIntf->takeFilters(std::move(filters));
620         return result;
621     }
622 
release()623     c2_status_t release() override {
624         c2_status_t result = mComp->release();
625         if (result != C2_OK) {
626             result = C2_CORRUPTED;
627         }
628         for (FilterWrapper::Component filter : mFilters) {
629             c2_status_t err = filter.comp->release();
630             if (err != C2_OK) {
631                 // Previous components are already released successfully;
632                 // we ended up in an incoherent state.
633                 result = C2_CORRUPTED;
634                 // continue for the rest of the chain
635             }
636         }
637         mRunningFilters.clear();
638         return result;
639     }
640 
641 private:
642     class PassingListener : public Listener {
643     public:
PassingListener(std::shared_ptr<C2Component> wrappedComponent,const std::shared_ptr<Listener> & wrappedComponentListener,std::shared_ptr<C2Component> nextComponent)644         PassingListener(
645                 std::shared_ptr<C2Component> wrappedComponent,
646                 const std::shared_ptr<Listener> &wrappedComponentListener,
647                 std::shared_ptr<C2Component> nextComponent)
648             : mWrappedComponent(wrappedComponent),
649               mWrappedComponentListener(wrappedComponentListener),
650               mNextComponent(nextComponent) {
651         }
652 
onWorkDone_nb(std::weak_ptr<C2Component>,std::list<std::unique_ptr<C2Work>> workItems)653         void onWorkDone_nb(
654                 std::weak_ptr<C2Component>,
655                 std::list<std::unique_ptr<C2Work>> workItems) override {
656             std::shared_ptr<C2Component> nextComponent = mNextComponent.lock();
657             std::list<std::unique_ptr<C2Work>> failedWorkItems;
658             if (!nextComponent) {
659                 for (std::unique_ptr<C2Work> &work : workItems) {
660                     // Next component unexpectedly released while the work is
661                     // in-flight. Report C2_CORRUPTED to the client.
662                     work->result = C2_CORRUPTED;
663                     failedWorkItems.push_back(std::move(work));
664                 }
665                 workItems.clear();
666             } else {
667                 for (auto it = workItems.begin(); it != workItems.end(); ) {
668                     const std::unique_ptr<C2Work> &work = *it;
669                     if (work->result != C2_OK
670                             || work->worklets.size() != 1) {
671                         failedWorkItems.push_back(std::move(*it));
672                         it = workItems.erase(it);
673                         continue;
674                     }
675                     C2FrameData &output = work->worklets.front()->output;
676                     c2_cntr64_t customOrdinal = work->input.ordinal.customOrdinal;
677                     work->input = std::move(output);
678                     work->input.ordinal.customOrdinal = customOrdinal;
679                     output.flags = C2FrameData::flags_t(0);
680                     output.buffers.clear();
681                     output.configUpdate.clear();
682                     output.infoBuffers.clear();
683                     ++it;
684                 }
685             }
686             if (!failedWorkItems.empty()) {
687                 for (const std::unique_ptr<C2Work> &work : failedWorkItems) {
688                     LOG(VERBOSE) << "work #" << work->input.ordinal.frameIndex.peek()
689                             << " failed: err=" << work->result
690                             << " worklets.size()=" << work->worklets.size();
691                 }
692                 if (std::shared_ptr<Listener> wrappedComponentListener =
693                         mWrappedComponentListener.lock()) {
694                     wrappedComponentListener->onWorkDone_nb(
695                             mWrappedComponent, std::move(failedWorkItems));
696                 }
697             }
698             if (!workItems.empty()) {
699                 nextComponent->queue_nb(&workItems);
700             }
701         }
702 
onTripped_nb(std::weak_ptr<C2Component>,std::vector<std::shared_ptr<C2SettingResult>>)703         void onTripped_nb(
704                 std::weak_ptr<C2Component>,
705                 std::vector<std::shared_ptr<C2SettingResult>>) override {
706             // Trip not supported
707         }
708 
onError_nb(std::weak_ptr<C2Component>,uint32_t errorCode)709         void onError_nb(std::weak_ptr<C2Component>, uint32_t errorCode) {
710             if (std::shared_ptr<Listener> wrappedComponentListener =
711                     mWrappedComponentListener.lock()) {
712                 wrappedComponentListener->onError_nb(mWrappedComponent, errorCode);
713             }
714         }
715 
716     private:
717         std::weak_ptr<C2Component> mWrappedComponent;
718         std::weak_ptr<Listener> mWrappedComponentListener;
719         std::weak_ptr<C2Component> mNextComponent;
720     };
721 
722     class LastListener : public Listener {
723     public:
LastListener(std::shared_ptr<C2Component> wrappedComponent,const std::shared_ptr<Listener> & wrappedComponentListener)724         LastListener(
725                 std::shared_ptr<C2Component> wrappedComponent,
726                 const std::shared_ptr<Listener> &wrappedComponentListener)
727             : mWrappedComponent(wrappedComponent),
728               mWrappedComponentListener(wrappedComponentListener) {
729         }
730 
onWorkDone_nb(std::weak_ptr<C2Component>,std::list<std::unique_ptr<C2Work>> workItems)731         void onWorkDone_nb(
732                 std::weak_ptr<C2Component>,
733                 std::list<std::unique_ptr<C2Work>> workItems) override {
734             if (mWrappedComponent.expired()) {
735                 return;
736             }
737             if (std::shared_ptr<Listener> wrappedComponentListener =
738                     mWrappedComponentListener.lock()) {
739                 wrappedComponentListener->onWorkDone_nb(
740                         mWrappedComponent, std::move(workItems));
741             }
742         }
743 
onTripped_nb(std::weak_ptr<C2Component>,std::vector<std::shared_ptr<C2SettingResult>>)744         void onTripped_nb(
745                 std::weak_ptr<C2Component>,
746                 std::vector<std::shared_ptr<C2SettingResult>>) override {
747             // Trip not supported
748         }
749 
onError_nb(std::weak_ptr<C2Component>,uint32_t errorCode)750         void onError_nb(std::weak_ptr<C2Component>, uint32_t errorCode) {
751             if (mWrappedComponent.expired()) {
752                 return;
753             }
754             if (std::shared_ptr<Listener> wrappedComponentListener =
755                     mWrappedComponentListener.lock()) {
756                 wrappedComponentListener->onError_nb(mWrappedComponent, errorCode);
757             }
758         }
759 
760     private:
761         std::weak_ptr<C2Component> mWrappedComponent;
762         std::weak_ptr<Listener> mWrappedComponentListener;
763     };
764 
765     std::shared_ptr<C2Component> mComp;
766     std::shared_ptr<WrappedDecoderInterface> mIntf;
767     std::vector<FilterWrapper::Component> mFilters;
768     std::vector<FilterWrapper::Component> mRunningFilters;
769     std::weak_ptr<FilterWrapper> mFilterWrapper;
770     std::shared_ptr<Listener> mListener;
771 #if defined(LOG_NDEBUG) && !LOG_NDEBUG
772     base::ScopedLogSeverity mScopedLogSeverity{base::VERBOSE};
773 #endif
774 
setListenerInternal(const std::vector<FilterWrapper::Component> & filters,const std::shared_ptr<Listener> & listener,c2_blocking_t mayBlock)775     c2_status_t setListenerInternal(
776             const std::vector<FilterWrapper::Component> &filters,
777             const std::shared_ptr<Listener> &listener,
778             c2_blocking_t mayBlock) {
779         if (filters.empty()) {
780             return mComp->setListener_vb(listener, mayBlock);
781         }
782         std::shared_ptr passingListener = std::make_shared<PassingListener>(
783                 shared_from_this(),
784                 listener,
785                 filters.front().comp);
786         mComp->setListener_vb(passingListener, mayBlock);
787         for (size_t i = 0; i < filters.size() - 1; ++i) {
788             filters[i].comp->setListener_vb(
789                     std::make_shared<PassingListener>(
790                             shared_from_this(),
791                             listener,
792                             filters[i + 1].comp),
793                     mayBlock);
794         }
795         filters.back().comp->setListener_vb(
796                 std::make_shared<LastListener>(shared_from_this(), listener), mayBlock);
797         return C2_OK;
798     }
799 };
800 
801 }  // anonymous namespace
802 
FilterWrapper(std::unique_ptr<Plugin> && plugin)803 FilterWrapper::FilterWrapper(std::unique_ptr<Plugin> &&plugin)
804     : mInit(NO_INIT),
805       mPlugin(std::move(plugin)) {
806     if (mPlugin->status() != OK) {
807         LOG(ERROR) << "plugin not OK: " << mPlugin->status();
808         mPlugin.reset();
809         return;
810     }
811     mStore = mPlugin->getStore();
812     if (!mStore) {
813         LOG(ERROR) << "no store";
814         mPlugin.reset();
815         return;
816     }
817     std::vector<std::shared_ptr<const C2Component::Traits>> traits =
818         mStore->listComponents();
819     std::sort(
820             traits.begin(),
821             traits.end(),
822             [](std::shared_ptr<const C2Component::Traits> &a,
823                     std::shared_ptr<const C2Component::Traits> &b) {
824                 return a->rank < b->rank;
825             });
826     for (size_t i = 0; i < traits.size(); ++i) {
827         const std::shared_ptr<const C2Component::Traits> &trait = traits[i];
828         if (trait->domain == C2Component::DOMAIN_OTHER
829                 || trait->domain == C2Component::DOMAIN_AUDIO
830                 || trait->kind != C2Component::KIND_OTHER) {
831             LOG(DEBUG) << trait->name << " is ignored because of domain/kind: "
832                 << trait->domain << "/" << trait->kind;
833             continue;
834         }
835         Descriptor desc;
836         if (!mPlugin->describe(trait->name, &desc)) {
837             LOG(DEBUG) << trait->name << " is ignored because describe() failed";
838             continue;
839         }
840         mComponents.push_back({nullptr, nullptr, *trait, desc});
841     }
842     if (mComponents.empty()) {
843         LOG(DEBUG) << "FilterWrapper: no filter component found";
844         mPlugin.reset();
845         return;
846     }
847     mInit = OK;
848 }
849 
~FilterWrapper()850 FilterWrapper::~FilterWrapper() {
851 }
852 
createFilters()853 std::vector<FilterWrapper::Component> FilterWrapper::createFilters() {
854     std::vector<FilterWrapper::Component> filters;
855     for (const FilterWrapper::Component &filter : mComponents) {
856         std::shared_ptr<C2Component> comp;
857         std::shared_ptr<C2ComponentInterface> intf;
858         if (C2_OK != mStore->createComponent(filter.traits.name, &comp)) {
859             return {};
860         }
861         filters.push_back({comp, comp->intf(), filter.traits, filter.desc});
862     }
863     return filters;
864 }
865 
getTraits(const std::shared_ptr<C2ComponentInterface> & intf)866 C2Component::Traits FilterWrapper::getTraits(
867         const std::shared_ptr<C2ComponentInterface> &intf) {
868     {
869         std::unique_lock lock(mCacheMutex);
870         if (mCachedTraits.count(intf->getName())) {
871             return mCachedTraits.at(intf->getName());
872         }
873     }
874     C2ComponentDomainSetting domain;
875     C2ComponentKindSetting kind;
876     c2_status_t err = intf->query_vb({&domain, &kind}, {}, C2_MAY_BLOCK, nullptr);
877     C2Component::Traits traits = {
878         "query failed",  // name
879         C2Component::DOMAIN_OTHER,
880         C2Component::KIND_OTHER,
881         0,   // rank, unused
882         "",  // media type, unused
883         "",  // owner, unused
884         {},  // aliases, unused
885     };
886     if (err == C2_OK) {
887         traits = {
888             intf->getName(),
889             domain.value,
890             kind.value,
891             0,   // rank, unused
892             "",  // media type, unused
893             "",  // owner, unused
894             {},  // aliases, unused
895         };
896         std::unique_lock lock(mCacheMutex);
897         mCachedTraits[traits.name] = traits;
898     }
899     return traits;
900 }
901 
maybeWrapInterface(const std::shared_ptr<C2ComponentInterface> intf)902 std::shared_ptr<C2ComponentInterface> FilterWrapper::maybeWrapInterface(
903         const std::shared_ptr<C2ComponentInterface> intf) {
904     if (mInit != OK) {
905         LOG(VERBOSE) << "maybeWrapInterface: Wrapper not initialized: "
906                 << intf->getName() << " is not wrapped.";
907         return intf;
908     }
909     C2Component::Traits traits = getTraits(intf);
910     if (traits.name != intf->getName()) {
911         LOG(INFO) << "maybeWrapInterface: Querying traits from " << intf->getName()
912                 << " failed; not wrapping the interface";
913         return intf;
914     }
915     if ((traits.domain != C2Component::DOMAIN_VIDEO && traits.domain != C2Component::DOMAIN_IMAGE)
916             || traits.kind != C2Component::KIND_DECODER) {
917         LOG(VERBOSE) << "maybeWrapInterface: " << traits.name
918                 << " is not video/image decoder; not wrapping the interface";
919         return intf;
920     }
921     return std::make_shared<WrappedDecoderInterface>(
922             intf, createFilters(), weak_from_this());
923 }
924 
maybeWrapComponent(const std::shared_ptr<C2Component> comp)925 std::shared_ptr<C2Component> FilterWrapper::maybeWrapComponent(
926         const std::shared_ptr<C2Component> comp) {
927     if (mInit != OK) {
928         LOG(VERBOSE) << "maybeWrapComponent: Wrapper not initialized: "
929                 << comp->intf()->getName() << " is not wrapped.";
930         return comp;
931     }
932     C2Component::Traits traits = getTraits(comp->intf());
933     if (traits.name != comp->intf()->getName()) {
934         LOG(INFO) << "maybeWrapComponent: Querying traits from " << comp->intf()->getName()
935                 << " failed; not wrapping the component";
936         return comp;
937     }
938     if ((traits.domain != C2Component::DOMAIN_VIDEO && traits.domain != C2Component::DOMAIN_IMAGE)
939             || traits.kind != C2Component::KIND_DECODER) {
940         LOG(VERBOSE) << "maybeWrapComponent: " << traits.name
941                 << " is not video/image decoder; not wrapping the component";
942         return comp;
943     }
944     std::vector<Component> filters = createFilters();
945     std::shared_ptr wrapped = std::make_shared<WrappedDecoder>(
946             comp, std::vector(filters), weak_from_this());
947     {
948         std::unique_lock lock(mWrappedComponentsMutex);
949         std::vector<std::weak_ptr<const C2Component>> &components =
950             mWrappedComponents.emplace_back();
951         components.push_back(wrapped);
952         components.push_back(comp);
953         for (const Component &filter : filters) {
954             components.push_back(filter.comp);
955         }
956     }
957     return wrapped;
958 }
959 
isFilteringEnabled(const std::shared_ptr<C2ComponentInterface> & intf)960 bool FilterWrapper::isFilteringEnabled(const std::shared_ptr<C2ComponentInterface> &intf) {
961     if (mInit != OK) {
962         LOG(WARNING) << "isFilteringEnabled: Wrapper not initialized: ";
963         return false;
964     }
965     return mPlugin->isFilteringEnabled(intf);
966 }
967 
createBlockPool(C2PlatformAllocatorStore::id_t allocatorId,std::shared_ptr<const C2Component> component,std::shared_ptr<C2BlockPool> * pool)968 c2_status_t FilterWrapper::createBlockPool(
969         C2PlatformAllocatorStore::id_t allocatorId,
970         std::shared_ptr<const C2Component> component,
971         std::shared_ptr<C2BlockPool> *pool) {
972     std::unique_lock lock(mWrappedComponentsMutex);
973     for (auto it = mWrappedComponents.begin(); it != mWrappedComponents.end(); ) {
974         std::shared_ptr<const C2Component> comp = it->front().lock();
975         if (!comp) {
976             it = mWrappedComponents.erase(it);
977             continue;
978         }
979         if (component == comp) {
980             std::vector<std::shared_ptr<const C2Component>> components(it->size());
981             std::transform(
982                     it->begin(), it->end(), components.begin(),
983                     [](const std::weak_ptr<const C2Component> &el) {
984                         return el.lock();
985                     });
986             if (C2_OK == CreateCodec2BlockPool(allocatorId, components, pool)) {
987                 return C2_OK;
988             }
989         }
990         ++it;
991     }
992     return CreateCodec2BlockPool(allocatorId, component, pool);
993 }
994 
queryParamsForPreviousComponent(const std::shared_ptr<C2ComponentInterface> & intf,std::vector<std::unique_ptr<C2Param>> * params)995 c2_status_t FilterWrapper::queryParamsForPreviousComponent(
996         const std::shared_ptr<C2ComponentInterface> &intf,
997         std::vector<std::unique_ptr<C2Param>> *params) {
998     if (mInit != OK) {
999         LOG(WARNING) << "queryParamsForPreviousComponent: Wrapper not initialized: ";
1000         return C2_NO_INIT;
1001     }
1002     return mPlugin->queryParamsForPreviousComponent(intf, params);
1003 }
1004 
1005 }  // namespace android
1006