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