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