blob: c620badfabae6b31764d5f1bf7cde40638c595a1 [file] [log] [blame]
Pawin Vongmasa36653902018-11-15 00:10:25 -08001/*
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002 * Copyright 2018 The Android Open Source Project
Pawin Vongmasa36653902018-11-15 00:10:25 -08003 *
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"
Pawin Vongmasa1c75a232019-01-09 04:41:52 -080019#include <android-base/logging.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080020
21#include <codec2/hidl/client.h>
22
23#include <deque>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070024#include <iterator>
Pawin Vongmasa36653902018-11-15 00:10:25 -080025#include <limits>
26#include <map>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070027#include <mutex>
28#include <sstream>
29#include <thread>
Pawin Vongmasa36653902018-11-15 00:10:25 -080030#include <type_traits>
31#include <vector>
32
33#include <android-base/properties.h>
34#include <bufferpool/ClientManager.h>
35#include <cutils/native_handle.h>
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080036#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
37#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080038#include <hidl/HidlSupport.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080039
Sungtak Leed3318082018-09-07 15:52:43 -070040#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
Pawin Vongmasad0f0e142018-11-15 03:36:28 -080041#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>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070046#include <android/hidl/manager/1.2/IServiceManager.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080047
48#include <C2Debug.h>
49#include <C2BufferPriv.h>
50#include <C2PlatformSupport.h>
51
52namespace android {
53
54using ::android::hardware::hidl_vec;
55using ::android::hardware::hidl_string;
56using ::android::hardware::Return;
57using ::android::hardware::Void;
Pawin Vongmasa36653902018-11-15 00:10:25 -080058
Pawin Vongmasad0f0e142018-11-15 03:36:28 -080059using namespace ::android::hardware::media::c2::V1_0;
60using namespace ::android::hardware::media::c2::V1_0::utils;
Sungtak Leed3318082018-09-07 15:52:43 -070061using namespace ::android::hardware::media::bufferpool::V2_0;
62using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
Pawin Vongmasa36653902018-11-15 00:10:25 -080063
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080064using HGraphicBufferProducer1 = ::android::hardware::graphics::bufferqueue::
65 V1_0::IGraphicBufferProducer;
66using HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
67 V2_0::IGraphicBufferProducer;
68using B2HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
69 V2_0::utils::B2HGraphicBufferProducer;
70using H2BGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
71 V2_0::utils::H2BGraphicBufferProducer;
72
Pawin Vongmasa36653902018-11-15 00:10:25 -080073namespace /* unnamed */ {
74
75// c2_status_t value that corresponds to hwbinder transaction failure.
76constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
77
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070078// Searches for a name in GetServiceNames() and returns the index found. If the
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070079// name is not found, the returned index will be equal to
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070080// GetServiceNames().size().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070081size_t getServiceIndex(char const* name) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070082 std::vector<std::string> const& names = Codec2Client::GetServiceNames();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070083 size_t i = 0;
84 for (; i < names.size(); ++i) {
85 if (name == names[i]) {
86 break;
87 }
Pawin Vongmasa36653902018-11-15 00:10:25 -080088 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070089 return i;
Pawin Vongmasa36653902018-11-15 00:10:25 -080090}
91
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070092} // 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.
98class 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
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700107 // The index of the service. This is based on GetServiceNames().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700108 size_t mIndex;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700109 // Called by s() exactly once to initialize the cache. The index must be a
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700110 // valid index into the vector returned by GetServiceNames(). Calling
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700111 // init(index) will associate the cache to the service with name
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700112 // GetServiceNames()[index].
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700113 void init(size_t index) {
114 mIndex = index;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700115 }
116
117public:
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.
123 std::shared_ptr<Codec2Client> getClient() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700124 std::scoped_lock lock{mClientMutex};
125 if (!mClient) {
126 mClient = Codec2Client::_CreateFromIndex(mIndex);
127 }
128 return mClient;
129 }
130
131 // Causes a subsequent call to getClient() to create a new client. This
132 // function should be called after the service dies.
133 //
134 // Note: This function is called only by ForAllServices().
135 void invalidate() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700136 std::scoped_lock lock{mClientMutex};
137 mClient = nullptr;
138 }
139
140 // Returns a list of traits for components supported by the service. This
141 // list is cached.
142 std::vector<C2Component::Traits> const& getTraits() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700143 std::call_once(mTraitsInitializationFlag, [this]() {
144 bool success{false};
145 // Spin until _listComponents() is successful.
146 while (true) {
147 std::shared_ptr<Codec2Client> client = getClient();
148 mTraits = client->_listComponents(&success);
149 if (success) {
150 break;
151 }
152 using namespace std::chrono_literals;
153 static constexpr auto kServiceRetryPeriod = 5s;
154 LOG(INFO) << "Failed to retrieve component traits from service "
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700155 "\"" << GetServiceNames()[mIndex] << "\". "
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700156 "Retrying...";
157 std::this_thread::sleep_for(kServiceRetryPeriod);
158 }
159 });
160 return mTraits;
161 }
162
163 // List() returns the list of all caches.
164 static std::vector<Cache>& List() {
165 static std::vector<Cache> sCaches{[]() {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700166 size_t numServices = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700167 std::vector<Cache> caches(numServices);
168 for (size_t i = 0; i < numServices; ++i) {
169 caches[i].init(i);
170 }
171 return caches;
172 }()};
173 return sCaches;
174 }
175};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800176
177// Codec2ConfigurableClient
178
179const C2String& Codec2ConfigurableClient::getName() const {
180 return mName;
181}
182
Pawin Vongmasa36653902018-11-15 00:10:25 -0800183Codec2ConfigurableClient::Codec2ConfigurableClient(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800184 const sp<IConfigurable>& base)
185 : mBase{base},
186 mName{[base]() -> C2String {
187 C2String outName;
188 Return<void> transStatus = base->getName(
189 [&outName](const hidl_string& name) {
190 outName = name.c_str();
191 });
192 return transStatus.isOk() ? outName : "";
193 }()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800194}
195
196c2_status_t Codec2ConfigurableClient::query(
197 const std::vector<C2Param*> &stackParams,
198 const std::vector<C2Param::Index> &heapParamIndices,
199 c2_blocking_t mayBlock,
200 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
201 hidl_vec<ParamIndex> indices(
202 stackParams.size() + heapParamIndices.size());
203 size_t numIndices = 0;
204 for (C2Param* const& stackParam : stackParams) {
205 if (!stackParam) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800206 LOG(WARNING) << "query -- null stack param encountered.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800207 continue;
208 }
209 indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
210 }
211 size_t numStackIndices = numIndices;
212 for (const C2Param::Index& index : heapParamIndices) {
213 indices[numIndices++] =
214 static_cast<ParamIndex>(static_cast<uint32_t>(index));
215 }
216 indices.resize(numIndices);
217 if (heapParams) {
218 heapParams->reserve(heapParams->size() + numIndices);
219 }
220 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800221 Return<void> transStatus = mBase->query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800222 indices,
223 mayBlock == C2_MAY_BLOCK,
224 [&status, &numStackIndices, &stackParams, heapParams](
225 Status s, const Params& p) {
226 status = static_cast<c2_status_t>(s);
227 if (status != C2_OK && status != C2_BAD_INDEX) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800228 LOG(DEBUG) << "query -- call failed: "
229 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800230 return;
231 }
232 std::vector<C2Param*> paramPointers;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800233 if (!parseParamsBlob(&paramPointers, p)) {
234 LOG(ERROR) << "query -- error while parsing params.";
235 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800236 return;
237 }
238 size_t i = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800239 for (auto it = paramPointers.begin();
240 it != paramPointers.end(); ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800241 C2Param* paramPointer = *it;
242 if (numStackIndices > 0) {
243 --numStackIndices;
244 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800245 LOG(WARNING) << "query -- null stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800246 ++it;
247 continue;
248 }
249 for (; i < stackParams.size() && !stackParams[i]; ) {
250 ++i;
251 }
252 if (i >= stackParams.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800253 LOG(ERROR) << "query -- unexpected error.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800254 status = C2_CORRUPTED;
255 return;
256 }
257 if (stackParams[i]->index() != paramPointer->index()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800258 LOG(WARNING) << "query -- param skipped: "
259 "index = "
260 << stackParams[i]->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800261 stackParams[i++]->invalidate();
262 continue;
263 }
264 if (!stackParams[i++]->updateFrom(*paramPointer)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800265 LOG(WARNING) << "query -- param update failed: "
266 "index = "
267 << paramPointer->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800268 }
269 } else {
270 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800271 LOG(WARNING) << "query -- null heap param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800272 ++it;
273 continue;
274 }
275 if (!heapParams) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800276 LOG(WARNING) << "query -- "
277 "unexpected extra stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800278 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800279 heapParams->emplace_back(
280 C2Param::Copy(*paramPointer));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800281 }
282 }
283 ++it;
284 }
285 });
286 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800287 LOG(ERROR) << "query -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800288 return C2_TRANSACTION_FAILED;
289 }
290 return status;
291}
292
293c2_status_t Codec2ConfigurableClient::config(
294 const std::vector<C2Param*> &params,
295 c2_blocking_t mayBlock,
296 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
297 Params hidlParams;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800298 if (!createParamsBlob(&hidlParams, params)) {
299 LOG(ERROR) << "config -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800300 return C2_TRANSACTION_FAILED;
301 }
302 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800303 Return<void> transStatus = mBase->config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800304 hidlParams,
305 mayBlock == C2_MAY_BLOCK,
306 [&status, &params, failures](
307 Status s,
308 const hidl_vec<SettingResult> f,
309 const Params& o) {
310 status = static_cast<c2_status_t>(s);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800311 if (status != C2_OK && status != C2_BAD_INDEX) {
312 LOG(DEBUG) << "config -- call failed: "
313 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800314 }
315 size_t i = failures->size();
316 failures->resize(i + f.size());
317 for (const SettingResult& sf : f) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800318 if (!objcpy(&(*failures)[i++], sf)) {
319 LOG(ERROR) << "config -- "
320 << "invalid SettingResult returned.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800321 return;
322 }
323 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800324 if (!updateParamsFromBlob(params, o)) {
325 LOG(ERROR) << "config -- "
326 << "failed to parse returned params.";
327 status = C2_CORRUPTED;
328 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800329 });
330 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800331 LOG(ERROR) << "config -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800332 return C2_TRANSACTION_FAILED;
333 }
334 return status;
335}
336
337c2_status_t Codec2ConfigurableClient::querySupportedParams(
338 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
339 // TODO: Cache and query properly!
340 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800341 Return<void> transStatus = mBase->querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800342 std::numeric_limits<uint32_t>::min(),
343 std::numeric_limits<uint32_t>::max(),
344 [&status, params](
345 Status s,
346 const hidl_vec<ParamDescriptor>& p) {
347 status = static_cast<c2_status_t>(s);
348 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800349 LOG(DEBUG) << "querySupportedParams -- call failed: "
350 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800351 return;
352 }
353 size_t i = params->size();
354 params->resize(i + p.size());
355 for (const ParamDescriptor& sp : p) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800356 if (!objcpy(&(*params)[i++], sp)) {
357 LOG(ERROR) << "querySupportedParams -- "
358 << "invalid returned ParamDescriptor.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800359 return;
360 }
361 }
362 });
363 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800364 LOG(ERROR) << "querySupportedParams -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800365 return C2_TRANSACTION_FAILED;
366 }
367 return status;
368}
369
370c2_status_t Codec2ConfigurableClient::querySupportedValues(
371 std::vector<C2FieldSupportedValuesQuery>& fields,
372 c2_blocking_t mayBlock) const {
373 hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
374 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800375 if (!objcpy(&inFields[i], fields[i])) {
376 LOG(ERROR) << "querySupportedValues -- bad input";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800377 return C2_TRANSACTION_FAILED;
378 }
379 }
380
381 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800382 Return<void> transStatus = mBase->querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800383 inFields,
384 mayBlock == C2_MAY_BLOCK,
385 [&status, &inFields, &fields](
386 Status s,
387 const hidl_vec<FieldSupportedValuesQueryResult>& r) {
388 status = static_cast<c2_status_t>(s);
389 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800390 LOG(DEBUG) << "querySupportedValues -- call failed: "
391 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800392 return;
393 }
394 if (r.size() != fields.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800395 LOG(ERROR) << "querySupportedValues -- "
396 "input and output lists "
397 "have different sizes.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800398 status = C2_CORRUPTED;
399 return;
400 }
401 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800402 if (!objcpy(&fields[i], inFields[i], r[i])) {
403 LOG(ERROR) << "querySupportedValues -- "
404 "invalid returned value.";
405 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800406 return;
407 }
408 }
409 });
410 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800411 LOG(ERROR) << "querySupportedValues -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800412 return C2_TRANSACTION_FAILED;
413 }
414 return status;
415}
416
417// Codec2Client::Component::HidlListener
418struct Codec2Client::Component::HidlListener : public IComponentListener {
419 std::weak_ptr<Component> component;
420 std::weak_ptr<Listener> base;
421
422 virtual Return<void> onWorkDone(const WorkBundle& workBundle) override {
423 std::list<std::unique_ptr<C2Work>> workItems;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800424 if (!objcpy(&workItems, workBundle)) {
425 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800426 return Void();
427 }
428 // release input buffers potentially held by the component from queue
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800429 std::shared_ptr<Codec2Client::Component> strongComponent =
430 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800431 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800432 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800433 }
434 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800435 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800436 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800437 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800438 }
439 return Void();
440 }
441
442 virtual Return<void> onTripped(
443 const hidl_vec<SettingResult>& settingResults) override {
444 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
445 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800446 for (size_t i = 0; i < settingResults.size(); ++i) {
447 std::unique_ptr<C2SettingResult> c2SettingResult;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800448 if (!objcpy(&c2SettingResult, settingResults[i])) {
449 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800450 return Void();
451 }
452 c2SettingResults[i] = std::move(c2SettingResult);
453 }
454 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
455 listener->onTripped(component, c2SettingResults);
456 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800457 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800458 }
459 return Void();
460 }
461
462 virtual Return<void> onError(Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800463 LOG(DEBUG) << "onError --"
464 << " status = " << s
465 << ", errorCode = " << errorCode
466 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800467 if (std::shared_ptr<Listener> listener = base.lock()) {
468 listener->onError(component, s == Status::OK ?
469 errorCode : static_cast<c2_status_t>(s));
470 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800471 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800472 }
473 return Void();
474 }
475
476 virtual Return<void> onFramesRendered(
477 const hidl_vec<RenderedFrame>& renderedFrames) override {
478 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800479 if (!listener) {
480 LOG(DEBUG) << "onFramesRendered -- listener died.";
481 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800482 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800483 for (const RenderedFrame& renderedFrame : renderedFrames) {
484 listener->onFrameRendered(
485 renderedFrame.bufferQueueId,
486 renderedFrame.slotId,
487 renderedFrame.timestampNs);
488 }
489 return Void();
490 }
491
492 virtual Return<void> onInputBuffersReleased(
493 const hidl_vec<InputBuffer>& inputBuffers) override {
494 std::shared_ptr<Listener> listener = base.lock();
495 if (!listener) {
496 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
497 return Void();
498 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800499 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800500 LOG(VERBOSE) << "onInputBuffersReleased --"
501 " received death notification of"
502 " input buffer:"
503 " frameIndex = " << inputBuffer.frameIndex
504 << ", bufferIndex = " << inputBuffer.arrayIndex
505 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -0800506 listener->onInputBufferDone(
507 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800508 }
509 return Void();
510 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800511
Pawin Vongmasa36653902018-11-15 00:10:25 -0800512};
513
514// Codec2Client
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800515Codec2Client::Codec2Client(const sp<IComponentStore>& base,
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700516 size_t serviceIndex)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800517 : Configurable{
518 [base]() -> sp<IConfigurable> {
519 Return<sp<IConfigurable>> transResult =
520 base->getConfigurable();
521 return transResult.isOk() ?
522 static_cast<sp<IConfigurable>>(transResult) :
523 nullptr;
524 }()
525 },
526 mBase{base},
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700527 mServiceIndex{serviceIndex} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800528 Return<sp<IClientManager>> transResult = base->getPoolClientManager();
529 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800530 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800531 } else {
532 mHostPoolManager = static_cast<sp<IClientManager>>(transResult);
533 }
534}
535
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700536sp<Codec2Client::Base> const& Codec2Client::getBase() const {
537 return mBase;
538}
539
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700540std::string const& Codec2Client::getServiceName() const {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700541 return GetServiceNames()[mServiceIndex];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700542}
543
Pawin Vongmasa36653902018-11-15 00:10:25 -0800544c2_status_t Codec2Client::createComponent(
545 const C2String& name,
546 const std::shared_ptr<Codec2Client::Listener>& listener,
547 std::shared_ptr<Codec2Client::Component>* const component) {
548
Pawin Vongmasa36653902018-11-15 00:10:25 -0800549 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800550 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800551 hidlListener->base = listener;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800552 Return<void> transStatus = mBase->createComponent(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800553 name,
554 hidlListener,
555 ClientManager::getInstance(),
556 [&status, component, hidlListener](
557 Status s,
558 const sp<IComponent>& c) {
559 status = static_cast<c2_status_t>(s);
560 if (status != C2_OK) {
561 return;
562 }
563 *component = std::make_shared<Codec2Client::Component>(c);
564 hidlListener->component = *component;
565 });
566 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800567 LOG(ERROR) << "createComponent(" << name.c_str()
568 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800569 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800570 } else if (status != C2_OK) {
571 LOG(ERROR) << "createComponent(" << name.c_str()
572 << ") -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800573 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800574 } else if (!*component) {
575 LOG(ERROR) << "createComponent(" << name.c_str()
576 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800577 return C2_CORRUPTED;
578 }
579
580 status = (*component)->setDeathListener(*component, listener);
581 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800582 LOG(ERROR) << "createComponent(" << name.c_str()
583 << ") -- failed to set up death listener: "
584 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800585 }
586
587 (*component)->mBufferPoolSender.setReceiver(mHostPoolManager);
588 return status;
589}
590
591c2_status_t Codec2Client::createInterface(
592 const C2String& name,
593 std::shared_ptr<Codec2Client::Interface>* const interface) {
594 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800595 Return<void> transStatus = mBase->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800596 name,
597 [&status, interface](
598 Status s,
599 const sp<IComponentInterface>& i) {
600 status = static_cast<c2_status_t>(s);
601 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800602 return;
603 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800604 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800605 });
606 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800607 LOG(ERROR) << "createInterface(" << name.c_str()
608 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800609 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800610 } else if (status != C2_OK) {
611 LOG(ERROR) << "createComponent(" << name.c_str()
612 << ") -- call failed: " << status << ".";
613 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800614 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800615
Pawin Vongmasa36653902018-11-15 00:10:25 -0800616 return status;
617}
618
619c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800620 std::shared_ptr<InputSurface>* const inputSurface) {
621 c2_status_t status;
622 Return<void> transStatus = mBase->createInputSurface(
623 [&status, inputSurface](
624 Status s,
625 const sp<IInputSurface>& i) {
626 status = static_cast<c2_status_t>(s);
627 if (status != C2_OK) {
628 return;
629 }
630 *inputSurface = std::make_shared<InputSurface>(i);
631 });
632 if (!transStatus.isOk()) {
633 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800634 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800635 } else if (status != C2_OK) {
636 LOG(DEBUG) << "createInputSurface -- call failed: "
637 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800638 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800639 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800640}
641
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700642std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
643 return Cache::List()[mServiceIndex].getTraits();
644}
645
646std::vector<C2Component::Traits> Codec2Client::_listComponents(
647 bool* success) const {
648 std::vector<C2Component::Traits> traits;
649 std::string const& serviceName = getServiceName();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800650 Return<void> transStatus = mBase->listComponents(
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700651 [&traits, &serviceName](Status s,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800652 const hidl_vec<IComponentStore::ComponentTraits>& t) {
653 if (s != Status::OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700654 LOG(DEBUG) << "_listComponents -- call failed: "
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800655 << static_cast<c2_status_t>(s) << ".";
656 return;
657 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700658 traits.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800659 for (size_t i = 0; i < t.size(); ++i) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700660 if (!objcpy(&traits[i], t[i])) {
661 LOG(ERROR) << "_listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800662 return;
663 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700664 traits[i].owner = serviceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800665 }
666 });
667 if (!transStatus.isOk()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700668 LOG(ERROR) << "_listComponents -- transaction failed.";
669 *success = false;
670 } else {
671 *success = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800672 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700673 return traits;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800674}
675
676c2_status_t Codec2Client::copyBuffer(
677 const std::shared_ptr<C2Buffer>& src,
678 const std::shared_ptr<C2Buffer>& dst) {
679 // TODO: Implement?
680 (void)src;
681 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800682 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800683 return C2_OMITTED;
684}
685
686std::shared_ptr<C2ParamReflector>
687 Codec2Client::getParamReflector() {
688 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
689 // should reflect the HAL API.
690 struct SimpleParamReflector : public C2ParamReflector {
691 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
692 hidl_vec<ParamIndex> indices(1);
693 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
694 std::unique_ptr<C2StructDescriptor> descriptor;
695 Return<void> transStatus = mBase->getStructDescriptors(
696 indices,
697 [&descriptor](
698 Status s,
699 const hidl_vec<StructDescriptor>& sd) {
700 c2_status_t status = static_cast<c2_status_t>(s);
701 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800702 LOG(DEBUG) << "SimpleParamReflector -- "
703 "getStructDescriptors() failed: "
704 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800705 descriptor.reset();
706 return;
707 }
708 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800709 LOG(DEBUG) << "SimpleParamReflector -- "
710 "getStructDescriptors() "
711 "returned vector of size "
712 << sd.size() << ". "
713 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800714 descriptor.reset();
715 return;
716 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800717 if (!objcpy(&descriptor, sd[0])) {
718 LOG(DEBUG) << "SimpleParamReflector -- "
719 "getStructDescriptors() returned "
720 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800721 descriptor.reset();
722 return;
723 }
724 });
725 return descriptor;
726 }
727
728 SimpleParamReflector(sp<Base> base)
729 : mBase(base) { }
730
731 sp<Base> mBase;
732 };
733
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800734 return std::make_shared<SimpleParamReflector>(mBase);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800735};
736
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700737std::vector<std::string> const& Codec2Client::GetServiceNames() {
738 static std::vector<std::string> sServiceNames{[]() {
739 using ::android::hardware::media::c2::V1_0::IComponentStore;
740 using ::android::hidl::manager::V1_2::IServiceManager;
741
742 while (true) {
743 sp<IServiceManager> serviceManager = IServiceManager::getService();
744 CHECK(serviceManager) << "Hardware service manager is not running.";
745
746 // There are three categories of services based on names.
747 std::vector<std::string> defaultNames; // Prefixed with "default"
748 std::vector<std::string> vendorNames; // Prefixed with "vendor"
749 std::vector<std::string> otherNames; // Others
750 Return<void> transResult;
751 transResult = serviceManager->listManifestByInterface(
752 IComponentStore::descriptor,
753 [&defaultNames, &vendorNames, &otherNames](
754 hidl_vec<hidl_string> const& instanceNames) {
755 for (hidl_string const& instanceName : instanceNames) {
756 char const* name = instanceName.c_str();
757 if (strncmp(name, "default", 7) == 0) {
758 defaultNames.emplace_back(name);
759 } else if (strncmp(name, "vendor", 6) == 0) {
760 vendorNames.emplace_back(name);
761 } else {
762 otherNames.emplace_back(name);
763 }
764 }
765 });
766 if (transResult.isOk()) {
767 // Sort service names in each category.
768 std::sort(defaultNames.begin(), defaultNames.end());
769 std::sort(vendorNames.begin(), vendorNames.end());
770 std::sort(otherNames.begin(), otherNames.end());
771
772 // Concatenate the three lists in this order: default, vendor,
773 // other.
774 std::vector<std::string>& names = defaultNames;
775 names.reserve(names.size() + vendorNames.size() + otherNames.size());
776 names.insert(names.end(),
777 std::make_move_iterator(vendorNames.begin()),
778 std::make_move_iterator(vendorNames.end()));
779 names.insert(names.end(),
780 std::make_move_iterator(otherNames.begin()),
781 std::make_move_iterator(otherNames.end()));
782
783 // Summarize to logcat.
784 if (names.empty()) {
785 LOG(INFO) << "No Codec2 services declared in the manifest.";
786 } else {
787 std::stringstream stringOutput;
788 stringOutput << "Available Codec2 services:";
789 for (std::string const& name : names) {
790 stringOutput << " \"" << name << "\"";
791 }
792 LOG(INFO) << stringOutput.str();
793 }
794
795 return names;
796 }
797 LOG(ERROR) << "Could not retrieve the list of service instances of "
798 << IComponentStore::descriptor
799 << ". Retrying...";
800 }
801 }()};
802 return sServiceNames;
803}
804
Pawin Vongmasa36653902018-11-15 00:10:25 -0800805std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700806 const char* name) {
807 size_t index = getServiceIndex(name);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700808 return index == GetServiceNames().size() ?
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700809 nullptr : _CreateFromIndex(index);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800810}
811
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700812std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
813 CreateFromAllServices() {
814 std::vector<std::shared_ptr<Codec2Client>> clients(
815 GetServiceNames().size());
816 for (size_t i = GetServiceNames().size(); i > 0; ) {
817 --i;
818 clients[i] = _CreateFromIndex(i);
819 }
820 return clients;
821}
822
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700823std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700824 std::string const& name = GetServiceNames()[index];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700825 LOG(INFO) << "Creating a Codec2 client to service \"" << name << "\"";
826 sp<Base> baseStore = Base::getService(name);
827 CHECK(baseStore) << "Codec2 service \"" << name << "\""
828 " inaccessible for unknown reasons.";
829 LOG(INFO) << "Client to Codec2 service \"" << name << "\" created";
830 return std::make_shared<Codec2Client>(baseStore, index);
831}
832
833c2_status_t Codec2Client::ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800834 const std::string &key,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800835 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
836 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800837 c2_status_t status = C2_NO_INIT; // no IComponentStores present
838
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700839 // Cache the mapping key -> index of Codec2Client in Cache::List().
Pawin Vongmasa36653902018-11-15 00:10:25 -0800840 static std::mutex key2IndexMutex;
841 static std::map<std::string, size_t> key2Index;
842
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800843 // By default try all stores. However, try the last known client first. If
844 // the last known client fails, retry once. We do this by pushing the last
845 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800846 std::deque<size_t> indices;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700847 for (size_t index = Cache::List().size(); index > 0; ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800848 indices.push_front(--index);
849 }
850
851 bool wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700852 {
853 std::scoped_lock lock{key2IndexMutex};
854 auto it = key2Index.find(key);
855 if (it != key2Index.end()) {
856 indices.push_front(it->second);
857 wasMapped = true;
858 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800859 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800860
861 for (size_t index : indices) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700862 Cache& cache = Cache::List()[index];
863 std::shared_ptr<Codec2Client> client{cache.getClient()};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800864 if (client) {
865 status = predicate(client);
866 if (status == C2_OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700867 std::scoped_lock lock{key2IndexMutex};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800868 key2Index[key] = index; // update last known client index
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700869 return C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800870 }
871 }
872 if (wasMapped) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800873 LOG(INFO) << "Could not find \"" << key << "\""
874 " in the last instance. Retrying...";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800875 wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700876 cache.invalidate();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800877 }
878 }
879 return status; // return the last status from a valid client
880}
881
882std::shared_ptr<Codec2Client::Component>
883 Codec2Client::CreateComponentByName(
884 const char* componentName,
885 const std::shared_ptr<Listener>& listener,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -0700886 std::shared_ptr<Codec2Client>* owner,
887 size_t numberOfAttempts) {
888 while (true) {
889 std::shared_ptr<Component> component;
890 c2_status_t status = ForAllServices(
891 componentName,
892 [owner, &component, componentName, &listener](
893 const std::shared_ptr<Codec2Client> &client)
894 -> c2_status_t {
895 c2_status_t status = client->createComponent(componentName,
896 listener,
897 &component);
898 if (status == C2_OK) {
899 if (owner) {
900 *owner = client;
901 }
902 } else if (status != C2_NOT_FOUND) {
903 LOG(DEBUG) << "IComponentStore("
904 << client->getServiceName()
905 << ")::createComponent(\"" << componentName
906 << "\") returned status = "
907 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800908 }
Pawin Vongmasa23c90c82019-09-03 00:44:42 -0700909 return status;
910 });
911 if (numberOfAttempts > 0 && status == C2_TRANSACTION_FAILED) {
912 --numberOfAttempts;
913 continue;
914 }
915 return component;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800916 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800917}
918
919std::shared_ptr<Codec2Client::Interface>
920 Codec2Client::CreateInterfaceByName(
921 const char* interfaceName,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -0700922 std::shared_ptr<Codec2Client>* owner,
923 size_t numberOfAttempts) {
924 while (true) {
925 std::shared_ptr<Interface> interface;
926 c2_status_t status = ForAllServices(
927 interfaceName,
928 [owner, &interface, interfaceName](
929 const std::shared_ptr<Codec2Client> &client)
930 -> c2_status_t {
931 c2_status_t status = client->createInterface(interfaceName,
932 &interface);
933 if (status == C2_OK) {
934 if (owner) {
935 *owner = client;
936 }
937 } else if (status != C2_NOT_FOUND) {
938 LOG(DEBUG) << "IComponentStore("
939 << client->getServiceName()
940 << ")::createInterface(\"" << interfaceName
941 << "\") returned status = "
942 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800943 }
Pawin Vongmasa23c90c82019-09-03 00:44:42 -0700944 return status;
945 });
946 if (numberOfAttempts > 0 && status == C2_TRANSACTION_FAILED) {
947 --numberOfAttempts;
948 continue;
949 }
950 return interface;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800951 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800952}
953
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700954std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
955 static std::vector<C2Component::Traits> sList{[]() {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800956 std::vector<C2Component::Traits> list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700957 for (Cache& cache : Cache::List()) {
958 std::vector<C2Component::Traits> const& traits = cache.getTraits();
959 list.insert(list.end(), traits.begin(), traits.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800960 }
961 return list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700962 }()};
963 return sList;
964}
Pawin Vongmasa36653902018-11-15 00:10:25 -0800965
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700966std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
967 char const* serviceName) {
Pawin Vongmasa18588322019-05-18 01:52:13 -0700968 int32_t inputSurfaceSetting = ::android::base::GetIntProperty(
969 "debug.stagefright.c2inputsurface", int32_t(0));
970 if (inputSurfaceSetting <= 0) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700971 return nullptr;
972 }
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700973 size_t index = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700974 if (serviceName) {
975 index = getServiceIndex(serviceName);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700976 if (index == GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700977 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
978 << serviceName << "\"";
979 }
980 }
981
982 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700983 if (index != GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700984 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
985 if (client->createInputSurface(&inputSurface) == C2_OK) {
986 return inputSurface;
987 }
988 }
989 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
990 "from all services...";
991 for (Cache& cache : Cache::List()) {
992 std::shared_ptr<Codec2Client> client = cache.getClient();
993 if (client->createInputSurface(&inputSurface) == C2_OK) {
994 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
995 "service \"" << client->getServiceName() << "\"";
996 return inputSurface;
997 }
998 }
999 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
1000 "from all services";
1001 return nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001002}
1003
1004// Codec2Client::Listener
1005
1006Codec2Client::Listener::~Listener() {
1007}
1008
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001009// Codec2Client::Interface
1010Codec2Client::Interface::Interface(const sp<Base>& base)
1011 : Configurable{
1012 [base]() -> sp<IConfigurable> {
1013 Return<sp<IConfigurable>> transResult =
1014 base->getConfigurable();
1015 return transResult.isOk() ?
1016 static_cast<sp<IConfigurable>>(transResult) :
1017 nullptr;
1018 }()
1019 },
1020 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001021}
1022
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001023// Codec2Client::Component
1024Codec2Client::Component::Component(const sp<Base>& base)
1025 : Configurable{
1026 [base]() -> sp<IConfigurable> {
1027 Return<sp<IComponentInterface>> transResult1 =
1028 base->getInterface();
1029 if (!transResult1.isOk()) {
1030 return nullptr;
1031 }
1032 Return<sp<IConfigurable>> transResult2 =
1033 static_cast<sp<IComponentInterface>>(transResult1)->
1034 getConfigurable();
1035 return transResult2.isOk() ?
1036 static_cast<sp<IConfigurable>>(transResult2) :
1037 nullptr;
1038 }()
1039 },
1040 mBase{base},
1041 mBufferPoolSender{nullptr} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001042}
1043
1044Codec2Client::Component::~Component() {
1045}
1046
1047c2_status_t Codec2Client::Component::createBlockPool(
1048 C2Allocator::id_t id,
1049 C2BlockPool::local_id_t* blockPoolId,
1050 std::shared_ptr<Codec2Client::Configurable>* configurable) {
1051 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001052 Return<void> transStatus = mBase->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001053 static_cast<uint32_t>(id),
1054 [&status, blockPoolId, configurable](
1055 Status s,
1056 uint64_t pId,
1057 const sp<IConfigurable>& c) {
1058 status = static_cast<c2_status_t>(s);
1059 configurable->reset();
1060 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001061 LOG(DEBUG) << "createBlockPool -- call failed: "
1062 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001063 return;
1064 }
1065 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001066 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001067 });
1068 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001069 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001070 return C2_TRANSACTION_FAILED;
1071 }
1072 return status;
1073}
1074
1075c2_status_t Codec2Client::Component::destroyBlockPool(
1076 C2BlockPool::local_id_t localId) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001077 Return<Status> transResult = mBase->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001078 static_cast<uint64_t>(localId));
1079 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001080 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001081 return C2_TRANSACTION_FAILED;
1082 }
1083 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1084}
1085
Wonsik Kimab34ed62019-01-31 15:28:46 -08001086void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001087 const std::list<std::unique_ptr<C2Work>> &workItems) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001088 // Output bufferqueue-based blocks' lifetime management
Sungtak Lee08515812019-06-05 11:16:32 -07001089 mOutputBufferQueue.holdBufferQueueBlocks(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001090}
1091
1092c2_status_t Codec2Client::Component::queue(
1093 std::list<std::unique_ptr<C2Work>>* const items) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001094 WorkBundle workBundle;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001095 if (!objcpy(&workBundle, *items, &mBufferPoolSender)) {
1096 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001097 return C2_TRANSACTION_FAILED;
1098 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001099 Return<Status> transStatus = mBase->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001100 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001101 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001102 return C2_TRANSACTION_FAILED;
1103 }
1104 c2_status_t status =
1105 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1106 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001107 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001108 }
1109 return status;
1110}
1111
1112c2_status_t Codec2Client::Component::flush(
1113 C2Component::flush_mode_t mode,
1114 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
1115 (void)mode; // Flush mode isn't supported in HIDL yet.
1116 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001117 Return<void> transStatus = mBase->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001118 [&status, flushedWork](
1119 Status s, const WorkBundle& wb) {
1120 status = static_cast<c2_status_t>(s);
1121 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001122 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001123 return;
1124 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001125 if (!objcpy(flushedWork, wb)) {
1126 status = C2_CORRUPTED;
1127 } else {
1128 status = C2_OK;
1129 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001130 });
1131 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001132 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001133 return C2_TRANSACTION_FAILED;
1134 }
1135
1136 // Indices of flushed work items.
1137 std::vector<uint64_t> flushedIndices;
1138 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
1139 if (work) {
1140 if (work->worklets.empty()
1141 || !work->worklets.back()
1142 || (work->worklets.back()->output.flags &
1143 C2FrameData::FLAG_INCOMPLETE) == 0) {
1144 // input is complete
1145 flushedIndices.emplace_back(
1146 work->input.ordinal.frameIndex.peeku());
1147 }
1148 }
1149 }
1150
Pawin Vongmasa36653902018-11-15 00:10:25 -08001151 // Output bufferqueue-based blocks' lifetime management
Sungtak Lee08515812019-06-05 11:16:32 -07001152 mOutputBufferQueue.holdBufferQueueBlocks(*flushedWork);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001153
1154 return status;
1155}
1156
1157c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001158 Return<Status> transStatus = mBase->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001159 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1160 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001161 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001162 return C2_TRANSACTION_FAILED;
1163 }
1164 c2_status_t status =
1165 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1166 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001167 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001168 }
1169 return status;
1170}
1171
1172c2_status_t Codec2Client::Component::start() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001173 Return<Status> transStatus = mBase->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001174 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001175 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001176 return C2_TRANSACTION_FAILED;
1177 }
1178 c2_status_t status =
1179 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1180 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001181 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001182 }
1183 return status;
1184}
1185
1186c2_status_t Codec2Client::Component::stop() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001187 Return<Status> transStatus = mBase->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001188 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001189 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001190 return C2_TRANSACTION_FAILED;
1191 }
1192 c2_status_t status =
1193 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1194 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001195 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001196 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001197 return status;
1198}
1199
1200c2_status_t Codec2Client::Component::reset() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001201 Return<Status> transStatus = mBase->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001202 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001203 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001204 return C2_TRANSACTION_FAILED;
1205 }
1206 c2_status_t status =
1207 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1208 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001209 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001210 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001211 return status;
1212}
1213
1214c2_status_t Codec2Client::Component::release() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001215 Return<Status> transStatus = mBase->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001216 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001217 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001218 return C2_TRANSACTION_FAILED;
1219 }
1220 c2_status_t status =
1221 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1222 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001223 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001224 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001225 return status;
1226}
1227
1228c2_status_t Codec2Client::Component::setOutputSurface(
1229 C2BlockPool::local_id_t blockPoolId,
1230 const sp<IGraphicBufferProducer>& surface,
1231 uint32_t generation) {
Sungtak Lee08515812019-06-05 11:16:32 -07001232 uint64_t bqId = 0;
1233 sp<IGraphicBufferProducer> nullIgbp;
1234 sp<HGraphicBufferProducer2> nullHgbp;
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08001235
Sungtak Lee08515812019-06-05 11:16:32 -07001236 sp<HGraphicBufferProducer2> igbp = surface ?
1237 surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
1238 if (surface && !igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001239 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001240 }
1241
Sungtak Lee08515812019-06-05 11:16:32 -07001242 if (!surface) {
1243 mOutputBufferQueue.configure(nullIgbp, generation, 0);
1244 } else if (surface->getUniqueId(&bqId) != OK) {
1245 LOG(ERROR) << "setOutputSurface -- "
1246 "cannot obtain bufferqueue id.";
1247 bqId = 0;
1248 mOutputBufferQueue.configure(nullIgbp, generation, 0);
1249 } else {
1250 mOutputBufferQueue.configure(surface, generation, bqId);
1251 }
1252 ALOGD("generation remote change %u", generation);
1253
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001254 Return<Status> transStatus = mBase->setOutputSurface(
Sungtak Lee08515812019-06-05 11:16:32 -07001255 static_cast<uint64_t>(blockPoolId),
1256 bqId == 0 ? nullHgbp : igbp);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001257 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001258 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001259 return C2_TRANSACTION_FAILED;
1260 }
1261 c2_status_t status =
1262 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1263 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001264 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001265 }
1266 return status;
1267}
1268
1269status_t Codec2Client::Component::queueToOutputSurface(
1270 const C2ConstGraphicBlock& block,
1271 const QueueBufferInput& input,
1272 QueueBufferOutput* output) {
Sungtak Lee08515812019-06-05 11:16:32 -07001273 return mOutputBufferQueue.outputBuffer(block, input, output);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001274}
1275
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001276c2_status_t Codec2Client::Component::connectToInputSurface(
1277 const std::shared_ptr<InputSurface>& inputSurface,
1278 std::shared_ptr<InputSurfaceConnection>* connection) {
1279 c2_status_t status;
1280 Return<void> transStatus = mBase->connectToInputSurface(
1281 inputSurface->mBase,
1282 [&status, connection](
1283 Status s, const sp<IInputSurfaceConnection>& c) {
1284 status = static_cast<c2_status_t>(s);
1285 if (status != C2_OK) {
1286 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1287 << status << ".";
1288 return;
1289 }
1290 *connection = std::make_shared<InputSurfaceConnection>(c);
1291 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001292 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001293 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001294 return C2_TRANSACTION_FAILED;
1295 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001296 return status;
1297}
1298
1299c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001300 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001301 const sp<HGraphicBufferSource>& source,
1302 std::shared_ptr<InputSurfaceConnection>* connection) {
1303 c2_status_t status;
1304 Return<void> transStatus = mBase->connectToOmxInputSurface(
1305 producer, source,
1306 [&status, connection](
1307 Status s, const sp<IInputSurfaceConnection>& c) {
1308 status = static_cast<c2_status_t>(s);
1309 if (status != C2_OK) {
1310 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1311 << status << ".";
1312 return;
1313 }
1314 *connection = std::make_shared<InputSurfaceConnection>(c);
1315 });
1316 if (!transStatus.isOk()) {
1317 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1318 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001319 }
1320 return status;
1321}
1322
1323c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001324 Return<Status> transStatus = mBase->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001325 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001326 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001327 return C2_TRANSACTION_FAILED;
1328 }
1329 c2_status_t status =
1330 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1331 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001332 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1333 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001334 }
1335 return status;
1336}
1337
1338c2_status_t Codec2Client::Component::setDeathListener(
1339 const std::shared_ptr<Component>& component,
1340 const std::shared_ptr<Listener>& listener) {
1341
1342 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1343 std::weak_ptr<Component> component;
1344 std::weak_ptr<Listener> base;
1345
1346 virtual void serviceDied(
1347 uint64_t /* cookie */,
1348 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1349 ) override {
1350 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1351 listener->onDeath(component);
1352 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001353 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001354 }
1355 }
1356 };
1357
1358 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1359 deathRecipient->base = listener;
1360 deathRecipient->component = component;
1361
1362 component->mDeathRecipient = deathRecipient;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001363 Return<bool> transResult = component->mBase->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001364 component->mDeathRecipient, 0);
1365 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001366 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001367 return C2_TRANSACTION_FAILED;
1368 }
1369 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001370 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001371 return C2_CORRUPTED;
1372 }
1373 return C2_OK;
1374}
1375
1376// Codec2Client::InputSurface
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001377Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base)
1378 : Configurable{
1379 [base]() -> sp<IConfigurable> {
1380 Return<sp<IConfigurable>> transResult =
1381 base->getConfigurable();
1382 return transResult.isOk() ?
1383 static_cast<sp<IConfigurable>>(transResult) :
1384 nullptr;
1385 }()
1386 },
1387 mBase{base},
1388 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001389 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
1390 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001391 base->getGraphicBufferProducer();
1392 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001393 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001394 nullptr;
1395 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001396}
1397
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001398sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08001399 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1400 return mGraphicBufferProducer;
1401}
1402
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001403sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001404 return mBase;
1405}
1406
1407// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08001408Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001409 const sp<IInputSurfaceConnection>& base)
1410 : Configurable{
1411 [base]() -> sp<IConfigurable> {
1412 Return<sp<IConfigurable>> transResult =
1413 base->getConfigurable();
1414 return transResult.isOk() ?
1415 static_cast<sp<IConfigurable>>(transResult) :
1416 nullptr;
1417 }()
1418 },
1419 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001420}
1421
1422c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001423 Return<Status> transResult = mBase->disconnect();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001424 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1425}
1426
1427} // namespace android
1428