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