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