1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "Codec2Client"
19 #include <log/log.h>
20
21 #include <codec2/hidl/client.h>
22
23 #include <deque>
24 #include <limits>
25 #include <map>
26 #include <type_traits>
27 #include <vector>
28
29 #include <android-base/properties.h>
30 #include <bufferpool/ClientManager.h>
31 #include <cutils/native_handle.h>
32 #include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
33 #include <gui/bufferqueue/1.0/WGraphicBufferProducer.h>
34 #include <hidl/HidlSupport.h>
35 #undef LOG
36
37 #include <android/hardware/media/bufferpool/1.0/IClientManager.h>
38 #include <hardware/google/media/c2/1.0/IComponent.h>
39 #include <hardware/google/media/c2/1.0/IComponentInterface.h>
40 #include <hardware/google/media/c2/1.0/IComponentListener.h>
41 #include <hardware/google/media/c2/1.0/IComponentStore.h>
42 #include <hardware/google/media/c2/1.0/IConfigurable.h>
43
44 #include <C2Debug.h>
45 #include <C2BufferPriv.h>
46 #include <C2PlatformSupport.h>
47
48 namespace android {
49
50 using ::android::hardware::hidl_vec;
51 using ::android::hardware::hidl_string;
52 using ::android::hardware::Return;
53 using ::android::hardware::Void;
54 using ::android::TWGraphicBufferProducer;
55
56 using namespace ::hardware::google::media::c2::V1_0;
57 using namespace ::hardware::google::media::c2::V1_0::utils;
58 using namespace ::android::hardware::media::bufferpool::V1_0;
59 using namespace ::android::hardware::media::bufferpool::V1_0::implementation;
60
61 namespace /* unnamed */ {
62
63 // c2_status_t value that corresponds to hwbinder transaction failure.
64 constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
65
66 // List of known IComponentStore services in the decreasing order of preference.
67 constexpr const char* kClientNames[] = {
68 "default",
69 "software",
70 };
71
72 // Number of known IComponentStore services.
73 constexpr size_t kNumClients = std::extent<decltype(kClientNames)>::value;
74
75 typedef std::array<std::shared_ptr<Codec2Client>, kNumClients> ClientList;
76
77 // Convenience methods to obtain known clients.
getClient(size_t index)78 std::shared_ptr<Codec2Client> getClient(size_t index) {
79 return Codec2Client::CreateFromService(kClientNames[index]);
80 }
81
getClientList()82 ClientList getClientList() {
83 ClientList list;
84 for (size_t i = 0; i < list.size(); ++i) {
85 list[i] = getClient(i);
86 }
87 return list;
88 }
89
90 } // unnamed
91
92 // Codec2ConfigurableClient
93
getName() const94 const C2String& Codec2ConfigurableClient::getName() const {
95 return mName;
96 }
97
base() const98 Codec2ConfigurableClient::Base* Codec2ConfigurableClient::base() const {
99 return static_cast<Base*>(mBase.get());
100 }
101
Codec2ConfigurableClient(const sp<Codec2ConfigurableClient::Base> & base)102 Codec2ConfigurableClient::Codec2ConfigurableClient(
103 const sp<Codec2ConfigurableClient::Base>& base) : mBase(base) {
104 Return<void> transStatus = base->getName(
105 [this](const hidl_string& name) {
106 mName = name.c_str();
107 });
108 if (!transStatus.isOk()) {
109 ALOGE("Cannot obtain name from IConfigurable.");
110 }
111 }
112
query(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,c2_blocking_t mayBlock,std::vector<std::unique_ptr<C2Param>> * const heapParams) const113 c2_status_t Codec2ConfigurableClient::query(
114 const std::vector<C2Param*> &stackParams,
115 const std::vector<C2Param::Index> &heapParamIndices,
116 c2_blocking_t mayBlock,
117 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
118 hidl_vec<ParamIndex> indices(
119 stackParams.size() + heapParamIndices.size());
120 size_t numIndices = 0;
121 for (C2Param* const& stackParam : stackParams) {
122 if (!stackParam) {
123 ALOGW("query -- null stack param encountered.");
124 continue;
125 }
126 indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
127 }
128 size_t numStackIndices = numIndices;
129 for (const C2Param::Index& index : heapParamIndices) {
130 indices[numIndices++] =
131 static_cast<ParamIndex>(static_cast<uint32_t>(index));
132 }
133 indices.resize(numIndices);
134 if (heapParams) {
135 heapParams->reserve(heapParams->size() + numIndices);
136 }
137 c2_status_t status;
138 Return<void> transStatus = base()->query(
139 indices,
140 mayBlock == C2_MAY_BLOCK,
141 [&status, &numStackIndices, &stackParams, heapParams](
142 Status s, const Params& p) {
143 status = static_cast<c2_status_t>(s);
144 if (status != C2_OK && status != C2_BAD_INDEX) {
145 ALOGE("query -- call failed. "
146 "Error code = %d", static_cast<int>(status));
147 return;
148 }
149 std::vector<C2Param*> paramPointers;
150 c2_status_t parseStatus = parseParamsBlob(¶mPointers, p);
151 if (parseStatus != C2_OK) {
152 ALOGE("query -- error while parsing params. "
153 "Error code = %d", static_cast<int>(status));
154 status = parseStatus;
155 return;
156 }
157 size_t i = 0;
158 for (auto it = paramPointers.begin(); it != paramPointers.end(); ) {
159 C2Param* paramPointer = *it;
160 if (numStackIndices > 0) {
161 --numStackIndices;
162 if (!paramPointer) {
163 ALOGW("query -- null stack param.");
164 ++it;
165 continue;
166 }
167 for (; i < stackParams.size() && !stackParams[i]; ) {
168 ++i;
169 }
170 if (i >= stackParams.size()) {
171 ALOGE("query -- unexpected error.");
172 status = C2_CORRUPTED;
173 return;
174 }
175 if (stackParams[i]->index() != paramPointer->index()) {
176 ALOGW("query -- param skipped. index = %d",
177 static_cast<int>(stackParams[i]->index()));
178 stackParams[i++]->invalidate();
179 continue;
180 }
181 if (!stackParams[i++]->updateFrom(*paramPointer)) {
182 ALOGW("query -- param update failed. index = %d",
183 static_cast<int>(paramPointer->index()));
184 }
185 } else {
186 if (!paramPointer) {
187 ALOGW("query -- null heap param.");
188 ++it;
189 continue;
190 }
191 if (!heapParams) {
192 ALOGW("query -- unexpected extra stack param.");
193 } else {
194 heapParams->emplace_back(C2Param::Copy(*paramPointer));
195 }
196 }
197 ++it;
198 }
199 });
200 if (!transStatus.isOk()) {
201 ALOGE("query -- transaction failed.");
202 return C2_TRANSACTION_FAILED;
203 }
204 return status;
205 }
206
config(const std::vector<C2Param * > & params,c2_blocking_t mayBlock,std::vector<std::unique_ptr<C2SettingResult>> * const failures)207 c2_status_t Codec2ConfigurableClient::config(
208 const std::vector<C2Param*> ¶ms,
209 c2_blocking_t mayBlock,
210 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
211 Params hidlParams;
212 Status hidlStatus = createParamsBlob(&hidlParams, params);
213 if (hidlStatus != Status::OK) {
214 ALOGE("config -- bad input.");
215 return C2_TRANSACTION_FAILED;
216 }
217 c2_status_t status;
218 Return<void> transStatus = base()->config(
219 hidlParams,
220 mayBlock == C2_MAY_BLOCK,
221 [&status, ¶ms, failures](
222 Status s,
223 const hidl_vec<SettingResult> f,
224 const Params& o) {
225 status = static_cast<c2_status_t>(s);
226 if (status != C2_OK) {
227 ALOGD("config -- call failed. "
228 "Error code = %d", static_cast<int>(status));
229 }
230 size_t i = failures->size();
231 failures->resize(i + f.size());
232 for (const SettingResult& sf : f) {
233 status = objcpy(&(*failures)[i++], sf);
234 if (status != C2_OK) {
235 ALOGE("config -- invalid returned SettingResult. "
236 "Error code = %d", static_cast<int>(status));
237 return;
238 }
239 }
240 status = updateParamsFromBlob(params, o);
241 });
242 if (!transStatus.isOk()) {
243 ALOGE("config -- transaction failed.");
244 return C2_TRANSACTION_FAILED;
245 }
246 return status;
247 }
248
querySupportedParams(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const249 c2_status_t Codec2ConfigurableClient::querySupportedParams(
250 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
251 // TODO: Cache and query properly!
252 c2_status_t status;
253 Return<void> transStatus = base()->querySupportedParams(
254 std::numeric_limits<uint32_t>::min(),
255 std::numeric_limits<uint32_t>::max(),
256 [&status, params](
257 Status s,
258 const hidl_vec<ParamDescriptor>& p) {
259 status = static_cast<c2_status_t>(s);
260 if (status != C2_OK) {
261 ALOGE("querySupportedParams -- call failed. "
262 "Error code = %d", static_cast<int>(status));
263 return;
264 }
265 size_t i = params->size();
266 params->resize(i + p.size());
267 for (const ParamDescriptor& sp : p) {
268 status = objcpy(&(*params)[i++], sp);
269 if (status != C2_OK) {
270 ALOGE("querySupportedParams -- "
271 "invalid returned ParamDescriptor. "
272 "Error code = %d", static_cast<int>(status));
273 return;
274 }
275 }
276 });
277 if (!transStatus.isOk()) {
278 ALOGE("querySupportedParams -- transaction failed.");
279 return C2_TRANSACTION_FAILED;
280 }
281 return status;
282 }
283
querySupportedValues(std::vector<C2FieldSupportedValuesQuery> & fields,c2_blocking_t mayBlock) const284 c2_status_t Codec2ConfigurableClient::querySupportedValues(
285 std::vector<C2FieldSupportedValuesQuery>& fields,
286 c2_blocking_t mayBlock) const {
287 hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
288 for (size_t i = 0; i < fields.size(); ++i) {
289 Status hidlStatus = objcpy(&inFields[i], fields[i]);
290 if (hidlStatus != Status::OK) {
291 ALOGE("querySupportedValues -- bad input");
292 return C2_TRANSACTION_FAILED;
293 }
294 }
295
296 c2_status_t status;
297 Return<void> transStatus = base()->querySupportedValues(
298 inFields,
299 mayBlock == C2_MAY_BLOCK,
300 [&status, &inFields, &fields](
301 Status s,
302 const hidl_vec<FieldSupportedValuesQueryResult>& r) {
303 status = static_cast<c2_status_t>(s);
304 if (status != C2_OK) {
305 ALOGE("querySupportedValues -- call failed. "
306 "Error code = %d", static_cast<int>(status));
307 return;
308 }
309 if (r.size() != fields.size()) {
310 ALOGE("querySupportedValues -- input and output lists "
311 "have different sizes.");
312 status = C2_CORRUPTED;
313 return;
314 }
315 for (size_t i = 0; i < fields.size(); ++i) {
316 status = objcpy(&fields[i], inFields[i], r[i]);
317 if (status != C2_OK) {
318 ALOGE("querySupportedValues -- invalid returned value. "
319 "Error code = %d", static_cast<int>(status));
320 return;
321 }
322 }
323 });
324 if (!transStatus.isOk()) {
325 ALOGE("querySupportedValues -- transaction failed.");
326 return C2_TRANSACTION_FAILED;
327 }
328 return status;
329 }
330
331 // Codec2Client::Component::HidlListener
332 struct Codec2Client::Component::HidlListener : public IComponentListener {
333 std::weak_ptr<Component> component;
334 std::weak_ptr<Listener> base;
335
onWorkDoneandroid::Codec2Client::Component::HidlListener336 virtual Return<void> onWorkDone(const WorkBundle& workBundle) override {
337 std::list<std::unique_ptr<C2Work>> workItems;
338 c2_status_t status = objcpy(&workItems, workBundle);
339 if (status != C2_OK) {
340 ALOGI("onWorkDone -- received corrupted WorkBundle. "
341 "status = %d.", static_cast<int>(status));
342 return Void();
343 }
344 // release input buffers potentially held by the component from queue
345 size_t numDiscardedInputBuffers = 0;
346 std::shared_ptr<Codec2Client::Component> strongComponent = component.lock();
347 if (strongComponent) {
348 numDiscardedInputBuffers = strongComponent->handleOnWorkDone(workItems);
349 }
350 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
351 listener->onWorkDone(component, workItems, numDiscardedInputBuffers);
352 } else {
353 ALOGD("onWorkDone -- listener died.");
354 }
355 return Void();
356 }
357
onTrippedandroid::Codec2Client::Component::HidlListener358 virtual Return<void> onTripped(
359 const hidl_vec<SettingResult>& settingResults) override {
360 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
361 settingResults.size());
362 c2_status_t status;
363 for (size_t i = 0; i < settingResults.size(); ++i) {
364 std::unique_ptr<C2SettingResult> c2SettingResult;
365 status = objcpy(&c2SettingResult, settingResults[i]);
366 if (status != C2_OK) {
367 ALOGI("onTripped -- received corrupted SettingResult. "
368 "status = %d.", static_cast<int>(status));
369 return Void();
370 }
371 c2SettingResults[i] = std::move(c2SettingResult);
372 }
373 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
374 listener->onTripped(component, c2SettingResults);
375 } else {
376 ALOGD("onTripped -- listener died.");
377 }
378 return Void();
379 }
380
onErrorandroid::Codec2Client::Component::HidlListener381 virtual Return<void> onError(Status s, uint32_t errorCode) override {
382 ALOGD("onError -- status = %d, errorCode = %u.",
383 static_cast<int>(s),
384 static_cast<unsigned>(errorCode));
385 if (std::shared_ptr<Listener> listener = base.lock()) {
386 listener->onError(component, s == Status::OK ?
387 errorCode : static_cast<c2_status_t>(s));
388 } else {
389 ALOGD("onError -- listener died.");
390 }
391 return Void();
392 }
393
onFramesRenderedandroid::Codec2Client::Component::HidlListener394 virtual Return<void> onFramesRendered(
395 const hidl_vec<RenderedFrame>& renderedFrames) override {
396 std::shared_ptr<Listener> listener = base.lock();
397 std::vector<Codec2Client::Listener::RenderedFrame> rfs;
398 rfs.reserve(renderedFrames.size());
399 for (const RenderedFrame& rf : renderedFrames) {
400 if (rf.slotId >= 0) {
401 if (listener) {
402 rfs.emplace_back(rf.bufferQueueId,
403 rf.slotId,
404 rf.timestampNs);
405 }
406 } else {
407 std::shared_ptr<Codec2Client::Component> strongComponent =
408 component.lock();
409 if (strongComponent) {
410 uint64_t frameIndex = rf.bufferQueueId;
411 size_t bufferIndex = static_cast<size_t>(~rf.slotId);
412 ALOGV("Received death notification of input buffer: "
413 "frameIndex = %llu, bufferIndex = %zu.",
414 static_cast<long long unsigned>(frameIndex),
415 bufferIndex);
416 std::shared_ptr<C2Buffer> buffer =
417 strongComponent->freeInputBuffer(
418 frameIndex, bufferIndex);
419 if (buffer) {
420 listener->onInputBufferDone(buffer);
421 }
422 }
423 }
424 }
425 if (!rfs.empty()) {
426 if (listener) {
427 listener->onFramesRendered(rfs);
428 } else {
429 ALOGD("onFramesRendered -- listener died.");
430 }
431 }
432 return Void();
433 }
434 };
435
436 // Codec2Client
base() const437 Codec2Client::Base* Codec2Client::base() const {
438 return static_cast<Base*>(mBase.get());
439 }
440
Codec2Client(const sp<Codec2Client::Base> & base,std::string instanceName)441 Codec2Client::Codec2Client(const sp<Codec2Client::Base>& base, std::string instanceName) :
442 Codec2ConfigurableClient(base), mListed(false), mInstanceName(instanceName) {
443 Return<sp<IClientManager>> transResult = base->getPoolClientManager();
444 if (!transResult.isOk()) {
445 ALOGE("getPoolClientManager -- failed transaction.");
446 } else {
447 mHostPoolManager = static_cast<sp<IClientManager>>(transResult);
448 }
449 }
450
createComponent(const C2String & name,const std::shared_ptr<Codec2Client::Listener> & listener,std::shared_ptr<Codec2Client::Component> * const component)451 c2_status_t Codec2Client::createComponent(
452 const C2String& name,
453 const std::shared_ptr<Codec2Client::Listener>& listener,
454 std::shared_ptr<Codec2Client::Component>* const component) {
455
456 // TODO: Add support for Bufferpool
457
458
459 c2_status_t status;
460 sp<Component::HidlListener> hidlListener = new Component::HidlListener();
461 hidlListener->base = listener;
462 Return<void> transStatus = base()->createComponent(
463 name,
464 hidlListener,
465 ClientManager::getInstance(),
466 [&status, component, hidlListener](
467 Status s,
468 const sp<IComponent>& c) {
469 status = static_cast<c2_status_t>(s);
470 if (status != C2_OK) {
471 return;
472 }
473 *component = std::make_shared<Codec2Client::Component>(c);
474 hidlListener->component = *component;
475 });
476 if (!transStatus.isOk()) {
477 ALOGE("createComponent -- failed transaction.");
478 return C2_TRANSACTION_FAILED;
479 }
480
481 if (status != C2_OK) {
482 return status;
483 }
484
485 if (!*component) {
486 ALOGE("createComponent -- null component.");
487 return C2_CORRUPTED;
488 }
489
490 status = (*component)->setDeathListener(*component, listener);
491 if (status != C2_OK) {
492 ALOGE("createComponent -- setDeathListener returned error: %d.",
493 static_cast<int>(status));
494 }
495
496 (*component)->mBufferPoolSender.setReceiver(mHostPoolManager);
497 return status;
498 }
499
createInterface(const C2String & name,std::shared_ptr<Codec2Client::Interface> * const interface)500 c2_status_t Codec2Client::createInterface(
501 const C2String& name,
502 std::shared_ptr<Codec2Client::Interface>* const interface) {
503 c2_status_t status;
504 Return<void> transStatus = base()->createInterface(
505 name,
506 [&status, interface](
507 Status s,
508 const sp<IComponentInterface>& i) {
509 status = static_cast<c2_status_t>(s);
510 if (status != C2_OK) {
511 ALOGE("createInterface -- call failed. "
512 "Error code = %d", static_cast<int>(status));
513 return;
514 }
515 *interface = std::make_shared<Codec2Client::Interface>(i);
516 });
517 if (!transStatus.isOk()) {
518 ALOGE("createInterface -- failed transaction.");
519 return C2_TRANSACTION_FAILED;
520 }
521 return status;
522 }
523
createInputSurface(std::shared_ptr<Codec2Client::InputSurface> * const inputSurface)524 c2_status_t Codec2Client::createInputSurface(
525 std::shared_ptr<Codec2Client::InputSurface>* const inputSurface) {
526 Return<sp<IInputSurface>> transResult = base()->createInputSurface();
527 if (!transResult.isOk()) {
528 ALOGE("createInputSurface -- failed transaction.");
529 return C2_TRANSACTION_FAILED;
530 }
531 sp<IInputSurface> result = static_cast<sp<IInputSurface>>(transResult);
532 if (!result) {
533 *inputSurface = nullptr;
534 return C2_OK;
535 }
536 *inputSurface = std::make_shared<InputSurface>(result);
537 if (!*inputSurface) {
538 ALOGE("createInputSurface -- unknown error.");
539 return C2_CORRUPTED;
540 }
541 return C2_OK;
542 }
543
listComponents() const544 const std::vector<C2Component::Traits>& Codec2Client::listComponents() const {
545 std::lock_guard<std::mutex> lock(mMutex);
546 if (mListed) {
547 return mTraitsList;
548 }
549 Return<void> transStatus = base()->listComponents(
550 [this](const hidl_vec<IComponentStore::ComponentTraits>& t) {
551 mTraitsList.resize(t.size());
552 mAliasesBuffer.resize(t.size());
553 for (size_t i = 0; i < t.size(); ++i) {
554 c2_status_t status = objcpy(
555 &mTraitsList[i], &mAliasesBuffer[i], t[i]);
556 mTraitsList[i].owner = mInstanceName;
557 if (status != C2_OK) {
558 ALOGE("listComponents -- corrupted output.");
559 return;
560 }
561 }
562 });
563 if (!transStatus.isOk()) {
564 ALOGE("listComponents -- failed transaction.");
565 }
566 mListed = true;
567 return mTraitsList;
568 }
569
copyBuffer(const std::shared_ptr<C2Buffer> & src,const std::shared_ptr<C2Buffer> & dst)570 c2_status_t Codec2Client::copyBuffer(
571 const std::shared_ptr<C2Buffer>& src,
572 const std::shared_ptr<C2Buffer>& dst) {
573 // TODO: Implement?
574 (void)src;
575 (void)dst;
576 ALOGE("copyBuffer not implemented");
577 return C2_OMITTED;
578 }
579
580 std::shared_ptr<C2ParamReflector>
getParamReflector()581 Codec2Client::getParamReflector() {
582 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
583 // should reflect the HAL API.
584 struct SimpleParamReflector : public C2ParamReflector {
585 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
586 hidl_vec<ParamIndex> indices(1);
587 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
588 std::unique_ptr<C2StructDescriptor> descriptor;
589 Return<void> transStatus = mBase->getStructDescriptors(
590 indices,
591 [&descriptor](
592 Status s,
593 const hidl_vec<StructDescriptor>& sd) {
594 c2_status_t status = static_cast<c2_status_t>(s);
595 if (status != C2_OK) {
596 ALOGE("getStructDescriptors -- call failed. "
597 "Error code = %d", static_cast<int>(status));
598 descriptor.reset();
599 return;
600 }
601 if (sd.size() != 1) {
602 ALOGD("getStructDescriptors -- returned vector of size %zu.",
603 sd.size());
604 descriptor.reset();
605 return;
606 }
607 status = objcpy(&descriptor, sd[0]);
608 if (status != C2_OK) {
609 ALOGD("getStructDescriptors -- failed to convert. "
610 "Error code = %d", static_cast<int>(status));
611 descriptor.reset();
612 return;
613 }
614 });
615 return descriptor;
616 }
617
618 SimpleParamReflector(sp<Base> base)
619 : mBase(base) { }
620
621 sp<Base> mBase;
622 };
623
624 return std::make_shared<SimpleParamReflector>(base());
625 };
626
CreateFromService(const char * instanceName,bool waitForService)627 std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
628 const char* instanceName, bool waitForService) {
629 if (!instanceName) {
630 return nullptr;
631 }
632 sp<Base> baseStore = waitForService ?
633 Base::getService(instanceName) :
634 Base::tryGetService(instanceName);
635 if (!baseStore) {
636 if (waitForService) {
637 ALOGE("Codec2.0 service inaccessible. Check the device manifest.");
638 } else {
639 ALOGW("Codec2.0 service not available right now. Try again later.");
640 }
641 return nullptr;
642 }
643 return std::make_shared<Codec2Client>(baseStore, instanceName);
644 }
645
ForAllStores(const std::string & key,std::function<c2_status_t (const std::shared_ptr<Codec2Client> &)> predicate)646 c2_status_t Codec2Client::ForAllStores(
647 const std::string &key,
648 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)> predicate) {
649 c2_status_t status = C2_NO_INIT; // no IComponentStores present
650
651 // Cache the mapping key -> index of Codec2Client in getClient().
652 static std::mutex key2IndexMutex;
653 static std::map<std::string, size_t> key2Index;
654
655 // By default try all stores. However, try the last known client first. If the last known
656 // client fails, retry once. We do this by pushing the last known client in front of the
657 // list of all clients.
658 std::deque<size_t> indices;
659 for (size_t index = kNumClients; index > 0; ) {
660 indices.push_front(--index);
661 }
662
663 bool wasMapped = false;
664 std::unique_lock<std::mutex> lock(key2IndexMutex);
665 auto it = key2Index.find(key);
666 if (it != key2Index.end()) {
667 indices.push_front(it->second);
668 wasMapped = true;
669 }
670 lock.unlock();
671
672 for (size_t index : indices) {
673 std::shared_ptr<Codec2Client> client = getClient(index);
674 if (client) {
675 status = predicate(client);
676 if (status == C2_OK) {
677 lock.lock();
678 key2Index[key] = index; // update last known client index
679 return status;
680 }
681 }
682 if (wasMapped) {
683 ALOGI("Could not find '%s' in last instance. Retrying...", key.c_str());
684 wasMapped = false;
685 }
686 }
687 return status; // return the last status from a valid client
688 }
689
690 std::shared_ptr<Codec2Client::Component>
CreateComponentByName(const char * componentName,const std::shared_ptr<Listener> & listener,std::shared_ptr<Codec2Client> * owner)691 Codec2Client::CreateComponentByName(
692 const char* componentName,
693 const std::shared_ptr<Listener>& listener,
694 std::shared_ptr<Codec2Client>* owner) {
695 std::shared_ptr<Component> component;
696 c2_status_t status = ForAllStores(
697 componentName,
698 [owner, &component, componentName, &listener](
699 const std::shared_ptr<Codec2Client> &client) -> c2_status_t {
700 c2_status_t status = client->createComponent(componentName, listener, &component);
701 if (status == C2_OK) {
702 if (owner) {
703 *owner = client;
704 }
705 } else if (status != C2_NOT_FOUND) {
706 ALOGD("IComponentStore(%s)::createComponent('%s') returned %s",
707 client->getInstanceName().c_str(), componentName, asString(status));
708 }
709 return status;
710 });
711 if (status != C2_OK) {
712 ALOGI("Could not create component '%s' (%s)", componentName, asString(status));
713 }
714 return component;
715 }
716
717 std::shared_ptr<Codec2Client::Interface>
CreateInterfaceByName(const char * interfaceName,std::shared_ptr<Codec2Client> * owner)718 Codec2Client::CreateInterfaceByName(
719 const char* interfaceName,
720 std::shared_ptr<Codec2Client>* owner) {
721 std::shared_ptr<Interface> interface;
722 c2_status_t status = ForAllStores(
723 interfaceName,
724 [owner, &interface, interfaceName](
725 const std::shared_ptr<Codec2Client> &client) -> c2_status_t {
726 c2_status_t status = client->createInterface(interfaceName, &interface);
727 if (status == C2_OK) {
728 if (owner) {
729 *owner = client;
730 }
731 } else if (status != C2_NOT_FOUND) {
732 ALOGD("IComponentStore(%s)::createInterface('%s') returned %s",
733 client->getInstanceName().c_str(), interfaceName, asString(status));
734 }
735 return status;
736 });
737 if (status != C2_OK) {
738 ALOGI("Could not create interface '%s' (%s)", interfaceName, asString(status));
739 }
740 return interface;
741 }
742
CreateInputSurface()743 std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface() {
744 uint32_t serviceMask = ::android::base::GetUintProperty(
745 "debug.stagefright.c2inputsurface", uint32_t(0));
746 for (size_t i = 0; i < kNumClients; ++i) {
747 if ((1 << i) & serviceMask) {
748 std::shared_ptr<Codec2Client> client = getClient(i);
749 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
750 if (client &&
751 client->createInputSurface(&inputSurface) == C2_OK &&
752 inputSurface) {
753 return inputSurface;
754 }
755 }
756 }
757 ALOGW("Could not create an input surface from any Codec2.0 services.");
758 return nullptr;
759 }
760
ListComponents()761 const std::vector<C2Component::Traits>& Codec2Client::ListComponents() {
762 static std::vector<C2Component::Traits> traitsList = [](){
763 std::vector<C2Component::Traits> list;
764 size_t listSize = 0;
765 ClientList clientList = getClientList();
766 for (const std::shared_ptr<Codec2Client>& client : clientList) {
767 if (!client) {
768 continue;
769 }
770 listSize += client->listComponents().size();
771 }
772 list.reserve(listSize);
773 for (const std::shared_ptr<Codec2Client>& client : clientList) {
774 if (!client) {
775 continue;
776 }
777 list.insert(
778 list.end(),
779 client->listComponents().begin(),
780 client->listComponents().end());
781 }
782 return list;
783 }();
784
785 return traitsList;
786 }
787
788 // Codec2Client::Listener
789
~Listener()790 Codec2Client::Listener::~Listener() {
791 }
792
793 // Codec2Client::Component
794
base() const795 Codec2Client::Component::Base* Codec2Client::Component::base() const {
796 return static_cast<Base*>(mBase.get());
797 }
798
Component(const sp<Codec2Client::Component::Base> & base)799 Codec2Client::Component::Component(const sp<Codec2Client::Component::Base>& base) :
800 Codec2Client::Configurable(base),
801 mBufferPoolSender(nullptr) {
802 }
803
~Component()804 Codec2Client::Component::~Component() {
805 }
806
createBlockPool(C2Allocator::id_t id,C2BlockPool::local_id_t * blockPoolId,std::shared_ptr<Codec2Client::Configurable> * configurable)807 c2_status_t Codec2Client::Component::createBlockPool(
808 C2Allocator::id_t id,
809 C2BlockPool::local_id_t* blockPoolId,
810 std::shared_ptr<Codec2Client::Configurable>* configurable) {
811 c2_status_t status;
812 Return<void> transStatus = base()->createBlockPool(
813 static_cast<uint32_t>(id),
814 [&status, blockPoolId, configurable](
815 Status s,
816 uint64_t pId,
817 const sp<IConfigurable>& c) {
818 status = static_cast<c2_status_t>(s);
819 configurable->reset();
820 if (status != C2_OK) {
821 ALOGE("createBlockPool -- call failed. "
822 "Error code = %d", static_cast<int>(status));
823 return;
824 }
825 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
826 *configurable = std::make_shared<Codec2Client::Configurable>(c);
827 });
828 if (!transStatus.isOk()) {
829 ALOGE("createBlockPool -- transaction failed.");
830 return C2_TRANSACTION_FAILED;
831 }
832 return status;
833 }
834
destroyBlockPool(C2BlockPool::local_id_t localId)835 c2_status_t Codec2Client::Component::destroyBlockPool(
836 C2BlockPool::local_id_t localId) {
837 Return<Status> transResult = base()->destroyBlockPool(
838 static_cast<uint64_t>(localId));
839 if (!transResult.isOk()) {
840 ALOGE("destroyBlockPool -- transaction failed.");
841 return C2_TRANSACTION_FAILED;
842 }
843 return static_cast<c2_status_t>(static_cast<Status>(transResult));
844 }
845
handleOnWorkDone(const std::list<std::unique_ptr<C2Work>> & workItems)846 size_t Codec2Client::Component::handleOnWorkDone(
847 const std::list<std::unique_ptr<C2Work>> &workItems) {
848 // Input buffers' lifetime management
849 std::vector<uint64_t> inputDone;
850 for (const std::unique_ptr<C2Work> &work : workItems) {
851 if (work) {
852 if (work->worklets.empty()
853 || !work->worklets.back()
854 || (work->worklets.back()->output.flags & C2FrameData::FLAG_INCOMPLETE) == 0) {
855 // input is complete
856 inputDone.emplace_back(work->input.ordinal.frameIndex.peeku());
857 }
858 }
859 }
860
861 size_t numDiscardedInputBuffers = 0;
862 {
863 std::lock_guard<std::mutex> lock(mInputBuffersMutex);
864 for (uint64_t inputIndex : inputDone) {
865 auto it = mInputBuffers.find(inputIndex);
866 if (it == mInputBuffers.end()) {
867 ALOGV("onWorkDone -- returned consumed/unknown "
868 "input frame: index %llu",
869 (long long)inputIndex);
870 } else {
871 ALOGV("onWorkDone -- processed input frame: "
872 "index %llu (containing %zu buffers)",
873 (long long)inputIndex, it->second.size());
874 mInputBuffers.erase(it);
875 mInputBufferCount.erase(inputIndex);
876 ++numDiscardedInputBuffers;
877 }
878 }
879 }
880
881 // Output bufferqueue-based blocks' lifetime management
882 mOutputBufferQueueMutex.lock();
883 sp<IGraphicBufferProducer> igbp = mOutputIgbp;
884 uint64_t bqId = mOutputBqId;
885 uint32_t generation = mOutputGeneration;
886 mOutputBufferQueueMutex.unlock();
887
888 if (igbp) {
889 holdBufferQueueBlocks(workItems, igbp, bqId, generation);
890 }
891 return numDiscardedInputBuffers;
892 }
893
freeInputBuffer(uint64_t frameIndex,size_t bufferIndex)894 std::shared_ptr<C2Buffer> Codec2Client::Component::freeInputBuffer(
895 uint64_t frameIndex,
896 size_t bufferIndex) {
897 std::shared_ptr<C2Buffer> buffer;
898 std::lock_guard<std::mutex> lock(mInputBuffersMutex);
899 auto it = mInputBuffers.find(frameIndex);
900 if (it == mInputBuffers.end()) {
901 ALOGI("freeInputBuffer -- Unrecognized input frame index %llu.",
902 static_cast<long long unsigned>(frameIndex));
903 return nullptr;
904 }
905 if (bufferIndex >= it->second.size()) {
906 ALOGI("freeInputBuffer -- Input buffer no. %zu is invalid in "
907 "input frame index %llu.",
908 bufferIndex, static_cast<long long unsigned>(frameIndex));
909 return nullptr;
910 }
911 buffer = it->second[bufferIndex];
912 if (!buffer) {
913 ALOGI("freeInputBuffer -- Input buffer no. %zu in "
914 "input frame index %llu has already been freed.",
915 bufferIndex, static_cast<long long unsigned>(frameIndex));
916 return nullptr;
917 }
918 it->second[bufferIndex] = nullptr;
919 if (--mInputBufferCount[frameIndex] == 0) {
920 mInputBuffers.erase(it);
921 mInputBufferCount.erase(frameIndex);
922 }
923 return buffer;
924 }
925
queue(std::list<std::unique_ptr<C2Work>> * const items)926 c2_status_t Codec2Client::Component::queue(
927 std::list<std::unique_ptr<C2Work>>* const items) {
928 // remember input buffers queued to hold reference to them
929 {
930 std::lock_guard<std::mutex> lock(mInputBuffersMutex);
931 for (const std::unique_ptr<C2Work> &work : *items) {
932 if (!work) {
933 continue;
934 }
935 if (work->input.buffers.size() == 0) {
936 continue;
937 }
938
939 uint64_t inputIndex = work->input.ordinal.frameIndex.peeku();
940 auto res = mInputBuffers.emplace(inputIndex, work->input.buffers);
941 if (!res.second) {
942 // TODO: append? - for now we are replacing
943 res.first->second = work->input.buffers;
944 ALOGI("queue -- duplicate input frame: index %llu. "
945 "Discarding the old input frame...",
946 (long long)inputIndex);
947 }
948 mInputBufferCount[inputIndex] = work->input.buffers.size();
949 ALOGV("queue -- queueing input frame: "
950 "index %llu (containing %zu buffers)",
951 (long long)inputIndex, work->input.buffers.size());
952 }
953 }
954
955 WorkBundle workBundle;
956 Status hidlStatus = objcpy(&workBundle, *items, &mBufferPoolSender);
957 if (hidlStatus != Status::OK) {
958 ALOGE("queue -- bad input.");
959 return C2_TRANSACTION_FAILED;
960 }
961 Return<Status> transStatus = base()->queue(workBundle);
962 if (!transStatus.isOk()) {
963 ALOGE("queue -- transaction failed.");
964 return C2_TRANSACTION_FAILED;
965 }
966 c2_status_t status =
967 static_cast<c2_status_t>(static_cast<Status>(transStatus));
968 if (status != C2_OK) {
969 ALOGE("queue -- call failed. "
970 "Error code = %d", static_cast<int>(status));
971 }
972 return status;
973 }
974
flush(C2Component::flush_mode_t mode,std::list<std::unique_ptr<C2Work>> * const flushedWork)975 c2_status_t Codec2Client::Component::flush(
976 C2Component::flush_mode_t mode,
977 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
978 (void)mode; // Flush mode isn't supported in HIDL yet.
979 c2_status_t status;
980 Return<void> transStatus = base()->flush(
981 [&status, flushedWork](
982 Status s, const WorkBundle& wb) {
983 status = static_cast<c2_status_t>(s);
984 if (status != C2_OK) {
985 ALOGE("flush -- call failed. "
986 "Error code = %d", static_cast<int>(status));
987 return;
988 }
989 status = objcpy(flushedWork, wb);
990 });
991 if (!transStatus.isOk()) {
992 ALOGE("flush -- transaction failed.");
993 return C2_TRANSACTION_FAILED;
994 }
995
996 // Indices of flushed work items.
997 std::vector<uint64_t> flushedIndices;
998 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
999 if (work) {
1000 if (work->worklets.empty()
1001 || !work->worklets.back()
1002 || (work->worklets.back()->output.flags &
1003 C2FrameData::FLAG_INCOMPLETE) == 0) {
1004 // input is complete
1005 flushedIndices.emplace_back(
1006 work->input.ordinal.frameIndex.peeku());
1007 }
1008 }
1009 }
1010
1011 // Input buffers' lifetime management
1012 for (uint64_t flushedIndex : flushedIndices) {
1013 std::lock_guard<std::mutex> lock(mInputBuffersMutex);
1014 auto it = mInputBuffers.find(flushedIndex);
1015 if (it == mInputBuffers.end()) {
1016 ALOGV("flush -- returned consumed/unknown input frame: "
1017 "index %llu",
1018 (long long)flushedIndex);
1019 } else {
1020 ALOGV("flush -- returned unprocessed input frame: "
1021 "index %llu (containing %zu buffers)",
1022 (long long)flushedIndex, mInputBufferCount[flushedIndex]);
1023 mInputBuffers.erase(it);
1024 mInputBufferCount.erase(flushedIndex);
1025 }
1026 }
1027
1028 // Output bufferqueue-based blocks' lifetime management
1029 mOutputBufferQueueMutex.lock();
1030 sp<IGraphicBufferProducer> igbp = mOutputIgbp;
1031 uint64_t bqId = mOutputBqId;
1032 uint32_t generation = mOutputGeneration;
1033 mOutputBufferQueueMutex.unlock();
1034
1035 if (igbp) {
1036 holdBufferQueueBlocks(*flushedWork, igbp, bqId, generation);
1037 }
1038
1039 return status;
1040 }
1041
drain(C2Component::drain_mode_t mode)1042 c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
1043 Return<Status> transStatus = base()->drain(
1044 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1045 if (!transStatus.isOk()) {
1046 ALOGE("drain -- transaction failed.");
1047 return C2_TRANSACTION_FAILED;
1048 }
1049 c2_status_t status =
1050 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1051 if (status != C2_OK) {
1052 ALOGE("drain -- call failed. "
1053 "Error code = %d", static_cast<int>(status));
1054 }
1055 return status;
1056 }
1057
start()1058 c2_status_t Codec2Client::Component::start() {
1059 Return<Status> transStatus = base()->start();
1060 if (!transStatus.isOk()) {
1061 ALOGE("start -- transaction failed.");
1062 return C2_TRANSACTION_FAILED;
1063 }
1064 c2_status_t status =
1065 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1066 if (status != C2_OK) {
1067 ALOGE("start -- call failed. "
1068 "Error code = %d", static_cast<int>(status));
1069 }
1070 return status;
1071 }
1072
stop()1073 c2_status_t Codec2Client::Component::stop() {
1074 Return<Status> transStatus = base()->stop();
1075 if (!transStatus.isOk()) {
1076 ALOGE("stop -- transaction failed.");
1077 return C2_TRANSACTION_FAILED;
1078 }
1079 c2_status_t status =
1080 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1081 if (status != C2_OK) {
1082 ALOGE("stop -- call failed. "
1083 "Error code = %d", static_cast<int>(status));
1084 }
1085 mInputBuffersMutex.lock();
1086 mInputBuffers.clear();
1087 mInputBufferCount.clear();
1088 mInputBuffersMutex.unlock();
1089 return status;
1090 }
1091
reset()1092 c2_status_t Codec2Client::Component::reset() {
1093 Return<Status> transStatus = base()->reset();
1094 if (!transStatus.isOk()) {
1095 ALOGE("reset -- transaction failed.");
1096 return C2_TRANSACTION_FAILED;
1097 }
1098 c2_status_t status =
1099 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1100 if (status != C2_OK) {
1101 ALOGE("reset -- call failed. "
1102 "Error code = %d", static_cast<int>(status));
1103 }
1104 mInputBuffersMutex.lock();
1105 mInputBuffers.clear();
1106 mInputBufferCount.clear();
1107 mInputBuffersMutex.unlock();
1108 return status;
1109 }
1110
release()1111 c2_status_t Codec2Client::Component::release() {
1112 Return<Status> transStatus = base()->release();
1113 if (!transStatus.isOk()) {
1114 ALOGE("release -- transaction failed.");
1115 return C2_TRANSACTION_FAILED;
1116 }
1117 c2_status_t status =
1118 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1119 if (status != C2_OK) {
1120 ALOGE("release -- call failed. "
1121 "Error code = %d", static_cast<int>(status));
1122 }
1123 mInputBuffersMutex.lock();
1124 mInputBuffers.clear();
1125 mInputBufferCount.clear();
1126 mInputBuffersMutex.unlock();
1127 return status;
1128 }
1129
setOutputSurface(C2BlockPool::local_id_t blockPoolId,const sp<IGraphicBufferProducer> & surface,uint32_t generation)1130 c2_status_t Codec2Client::Component::setOutputSurface(
1131 C2BlockPool::local_id_t blockPoolId,
1132 const sp<IGraphicBufferProducer>& surface,
1133 uint32_t generation) {
1134 sp<HGraphicBufferProducer> igbp =
1135 surface->getHalInterface<HGraphicBufferProducer>();
1136 if (!igbp) {
1137 igbp = new TWGraphicBufferProducer<HGraphicBufferProducer>(surface);
1138 }
1139
1140 Return<Status> transStatus = base()->setOutputSurface(
1141 static_cast<uint64_t>(blockPoolId), igbp);
1142 if (!transStatus.isOk()) {
1143 ALOGE("setOutputSurface -- transaction failed.");
1144 return C2_TRANSACTION_FAILED;
1145 }
1146 c2_status_t status =
1147 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1148 if (status != C2_OK) {
1149 ALOGE("setOutputSurface -- call failed. "
1150 "Error code = %d", static_cast<int>(status));
1151 } else {
1152 std::lock_guard<std::mutex> lock(mOutputBufferQueueMutex);
1153 if (mOutputIgbp != surface) {
1154 mOutputIgbp = surface;
1155 if (!surface) {
1156 mOutputBqId = 0;
1157 } else if (surface->getUniqueId(&mOutputBqId) != OK) {
1158 ALOGE("setOutputSurface -- cannot obtain bufferqueue id.");
1159 }
1160 }
1161 mOutputGeneration = generation;
1162 }
1163 return status;
1164 }
1165
queueToOutputSurface(const C2ConstGraphicBlock & block,const QueueBufferInput & input,QueueBufferOutput * output)1166 status_t Codec2Client::Component::queueToOutputSurface(
1167 const C2ConstGraphicBlock& block,
1168 const QueueBufferInput& input,
1169 QueueBufferOutput* output) {
1170 uint32_t generation;
1171 uint64_t bqId;
1172 int32_t bqSlot;
1173 if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot) ||
1174 bqId == 0) {
1175 // Block not from bufferqueue -- it must be attached before queuing.
1176
1177 mOutputBufferQueueMutex.lock();
1178 sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp;
1179 uint32_t outputGeneration = mOutputGeneration;
1180 mOutputBufferQueueMutex.unlock();
1181
1182 status_t status = !attachToBufferQueue(block,
1183 outputIgbp,
1184 outputGeneration,
1185 &bqSlot);
1186 if (status != OK) {
1187 ALOGW("queueToOutputSurface -- attaching failed.");
1188 return INVALID_OPERATION;
1189 }
1190
1191 status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
1192 input, output);
1193 if (status != OK) {
1194 ALOGE("queueToOutputSurface -- queueBuffer() failed "
1195 "on non-bufferqueue-based block. "
1196 "Error code = %d.",
1197 static_cast<int>(status));
1198 return status;
1199 }
1200 return OK;
1201 }
1202
1203 mOutputBufferQueueMutex.lock();
1204 sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp;
1205 uint64_t outputBqId = mOutputBqId;
1206 uint32_t outputGeneration = mOutputGeneration;
1207 mOutputBufferQueueMutex.unlock();
1208
1209 if (!outputIgbp) {
1210 ALOGV("queueToOutputSurface -- output surface is null.");
1211 return NO_INIT;
1212 }
1213
1214 if (bqId != outputBqId) {
1215 ALOGV("queueToOutputSurface -- bufferqueue ids mismatch.");
1216 return DEAD_OBJECT;
1217 }
1218
1219 if (generation != outputGeneration) {
1220 ALOGV("queueToOutputSurface -- generation numbers mismatch.");
1221 return DEAD_OBJECT;
1222 }
1223
1224 status_t status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
1225 input, output);
1226 if (status != OK) {
1227 ALOGD("queueToOutputSurface -- queueBuffer() failed "
1228 "on bufferqueue-based block. "
1229 "Error code = %d.",
1230 static_cast<int>(status));
1231 return status;
1232 }
1233 if (!yieldBufferQueueBlock(block)) {
1234 ALOGD("queueToOutputSurface -- cannot yield bufferqueue-based block "
1235 "to the bufferqueue.");
1236 return UNKNOWN_ERROR;
1237 }
1238 return OK;
1239 }
1240
connectToOmxInputSurface(const sp<HGraphicBufferProducer> & producer,const sp<HGraphicBufferSource> & source)1241 c2_status_t Codec2Client::Component::connectToOmxInputSurface(
1242 const sp<HGraphicBufferProducer>& producer,
1243 const sp<HGraphicBufferSource>& source) {
1244 Return<Status> transStatus = base()->connectToOmxInputSurface(
1245 producer, source);
1246 if (!transStatus.isOk()) {
1247 ALOGE("connectToOmxInputSurface -- transaction failed.");
1248 return C2_TRANSACTION_FAILED;
1249 }
1250 c2_status_t status =
1251 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1252 if (status != C2_OK) {
1253 ALOGE("connectToOmxInputSurface -- call failed. "
1254 "Error code = %d", static_cast<int>(status));
1255 }
1256 return status;
1257 }
1258
disconnectFromInputSurface()1259 c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
1260 Return<Status> transStatus = base()->disconnectFromInputSurface();
1261 if (!transStatus.isOk()) {
1262 ALOGE("disconnectToInputSurface -- transaction failed.");
1263 return C2_TRANSACTION_FAILED;
1264 }
1265 c2_status_t status =
1266 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1267 if (status != C2_OK) {
1268 ALOGE("disconnectFromInputSurface -- call failed. "
1269 "Error code = %d", static_cast<int>(status));
1270 }
1271 return status;
1272 }
1273
setDeathListener(const std::shared_ptr<Component> & component,const std::shared_ptr<Listener> & listener)1274 c2_status_t Codec2Client::Component::setDeathListener(
1275 const std::shared_ptr<Component>& component,
1276 const std::shared_ptr<Listener>& listener) {
1277
1278 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1279 std::weak_ptr<Component> component;
1280 std::weak_ptr<Listener> base;
1281
1282 virtual void serviceDied(
1283 uint64_t /* cookie */,
1284 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1285 ) override {
1286 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1287 listener->onDeath(component);
1288 } else {
1289 ALOGW("onDeath -- listener died.");
1290 }
1291 }
1292 };
1293
1294 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1295 deathRecipient->base = listener;
1296 deathRecipient->component = component;
1297
1298 component->mDeathRecipient = deathRecipient;
1299 Return<bool> transResult = component->base()->linkToDeath(
1300 component->mDeathRecipient, 0);
1301 if (!transResult.isOk()) {
1302 ALOGE("setDeathListener -- failed transaction: linkToDeath.");
1303 return C2_TRANSACTION_FAILED;
1304 }
1305 if (!static_cast<bool>(transResult)) {
1306 ALOGE("setDeathListener -- linkToDeath call failed.");
1307 return C2_CORRUPTED;
1308 }
1309 return C2_OK;
1310 }
1311
1312 // Codec2Client::InputSurface
1313
base() const1314 Codec2Client::InputSurface::Base* Codec2Client::InputSurface::base() const {
1315 return static_cast<Base*>(mBase.get());
1316 }
1317
InputSurface(const sp<IInputSurface> & base)1318 Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base) :
1319 mBase(base),
1320 mGraphicBufferProducer(new
1321 ::android::hardware::graphics::bufferqueue::V1_0::utils::
1322 H2BGraphicBufferProducer(base)) {
1323 }
1324
connectToComponent(const std::shared_ptr<Codec2Client::Component> & component,std::shared_ptr<Connection> * connection)1325 c2_status_t Codec2Client::InputSurface::connectToComponent(
1326 const std::shared_ptr<Codec2Client::Component>& component,
1327 std::shared_ptr<Connection>* connection) {
1328 c2_status_t status;
1329 Return<void> transStatus = base()->connectToComponent(
1330 component->base(),
1331 [&status, connection](
1332 Status s,
1333 const sp<IInputSurfaceConnection>& c) {
1334 status = static_cast<c2_status_t>(s);
1335 if (status != C2_OK) {
1336 ALOGE("connectToComponent -- call failed. "
1337 "Error code = %d", static_cast<int>(status));
1338 return;
1339 }
1340 *connection = std::make_shared<Connection>(c);
1341 });
1342 if (!transStatus.isOk()) {
1343 ALOGE("connect -- transaction failed.");
1344 return C2_TRANSACTION_FAILED;
1345 }
1346 return status;
1347 }
1348
1349 std::shared_ptr<Codec2Client::Configurable>
getConfigurable() const1350 Codec2Client::InputSurface::getConfigurable() const {
1351 Return<sp<IConfigurable>> transResult = base()->getConfigurable();
1352 if (!transResult.isOk()) {
1353 ALOGW("getConfigurable -- transaction failed.");
1354 return nullptr;
1355 }
1356 if (!static_cast<sp<IConfigurable>>(transResult)) {
1357 ALOGW("getConfigurable -- null pointer.");
1358 return nullptr;
1359 }
1360 return std::make_shared<Configurable>(transResult);
1361 }
1362
1363 const sp<IGraphicBufferProducer>&
getGraphicBufferProducer() const1364 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1365 return mGraphicBufferProducer;
1366 }
1367
getHalInterface() const1368 const sp<IInputSurface>& Codec2Client::InputSurface::getHalInterface() const {
1369 return mBase;
1370 }
1371
1372 // Codec2Client::InputSurfaceConnection
1373
1374 Codec2Client::InputSurfaceConnection::Base*
base() const1375 Codec2Client::InputSurfaceConnection::base() const {
1376 return static_cast<Base*>(mBase.get());
1377 }
1378
InputSurfaceConnection(const sp<Codec2Client::InputSurfaceConnection::Base> & base)1379 Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
1380 const sp<Codec2Client::InputSurfaceConnection::Base>& base) :
1381 mBase(base) {
1382 }
1383
disconnect()1384 c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
1385 Return<Status> transResult = base()->disconnect();
1386 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1387 }
1388
1389 } // namespace android
1390
1391