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(¶mDescs);
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> ¶mDesc : 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> ¶m) {
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 *> ¶ms,
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> ¶mDesc : 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(¶mDescs);
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> ¶mDesc : 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, ¶ms);
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