blob: 53adbbc6d9d33257aec7e8463236f1e9ddfae887 [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 Vongmasa892c81d2019-03-12 00:56:50 -070078// Returns the list of IComponentStore service names that are available on the
79// device. This list is specified at the build time in manifest files.
80// Note: A software service will have "_software" as a suffix.
81std::vector<std::string> const& getServiceNames() {
82 static std::vector<std::string> sServiceNames{[]() {
83 using ::android::hardware::media::c2::V1_0::IComponentStore;
84 using ::android::hidl::manager::V1_2::IServiceManager;
Pawin Vongmasa36653902018-11-15 00:10:25 -080085
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070086 while (true) {
87 sp<IServiceManager> serviceManager = IServiceManager::getService();
88 CHECK(serviceManager) << "Hardware service manager is not running.";
Pawin Vongmasa36653902018-11-15 00:10:25 -080089
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070090 // There are three categories of services based on names.
91 std::vector<std::string> defaultNames; // Prefixed with "default"
92 std::vector<std::string> vendorNames; // Prefixed with "vendor"
93 std::vector<std::string> otherNames; // Others
94 Return<void> transResult;
95 transResult = serviceManager->listManifestByInterface(
96 IComponentStore::descriptor,
97 [&defaultNames, &vendorNames, &otherNames](
98 hidl_vec<hidl_string> const& instanceNames) {
99 for (hidl_string const& instanceName : instanceNames) {
100 char const* name = instanceName.c_str();
101 if (strncmp(name, "default", 7) == 0) {
102 defaultNames.emplace_back(name);
103 } else if (strncmp(name, "vendor", 6) == 0) {
104 vendorNames.emplace_back(name);
105 } else {
106 otherNames.emplace_back(name);
107 }
108 }
109 });
110 if (transResult.isOk()) {
111 // Sort service names in each category.
112 std::sort(defaultNames.begin(), defaultNames.end());
113 std::sort(vendorNames.begin(), vendorNames.end());
114 std::sort(otherNames.begin(), otherNames.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800115
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700116 // Concatenate the three lists in this order: default, vendor,
117 // other.
118 std::vector<std::string>& names = defaultNames;
119 names.reserve(names.size() + vendorNames.size() + otherNames.size());
120 names.insert(names.end(),
121 std::make_move_iterator(vendorNames.begin()),
122 std::make_move_iterator(vendorNames.end()));
123 names.insert(names.end(),
124 std::make_move_iterator(otherNames.begin()),
125 std::make_move_iterator(otherNames.end()));
126
127 // Summarize to logcat.
128 if (names.empty()) {
129 LOG(INFO) << "No Codec2 services declared in the manifest.";
130 } else {
131 std::stringstream stringOutput;
132 stringOutput << "Available Codec2 services:";
133 for (std::string const& name : names) {
134 stringOutput << " \"" << name << "\"";
135 }
136 LOG(INFO) << stringOutput.str();
137 }
138
139 return names;
140 }
141 LOG(ERROR) << "Could not retrieve the list of service instances of "
142 << IComponentStore::descriptor
143 << ". Retrying...";
144 }
145 }()};
146 return sServiceNames;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800147}
148
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700149// Searches for a name in getServiceNames() and returns the index found. If the
150// name is not found, the returned index will be equal to
151// getServiceNames().size().
152size_t getServiceIndex(char const* name) {
153 std::vector<std::string> const& names = getServiceNames();
154 size_t i = 0;
155 for (; i < names.size(); ++i) {
156 if (name == names[i]) {
157 break;
158 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800159 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700160 return i;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800161}
162
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700163} // unnamed namespace
164
165// This class caches a Codec2Client object and its component traits. The client
166// will be created the first time it is needed, and it can be refreshed if the
167// service dies (by calling invalidate()). The first time listComponents() is
168// called from the client, the result will be cached.
169class Codec2Client::Cache {
170 // Cached client
171 std::shared_ptr<Codec2Client> mClient;
172 mutable std::mutex mClientMutex;
173
174 // Cached component traits
175 std::vector<C2Component::Traits> mTraits;
176 std::once_flag mTraitsInitializationFlag;
177
178 // The index of the service. This is based on getServiceNames().
179 size_t mIndex;
180 // A "valid" cache object must have its mIndex set with init().
181 bool mValid{false};
182 // Called by s() exactly once to initialize the cache. The index must be a
183 // valid index into the vector returned by getServiceNames(). Calling
184 // init(index) will associate the cache to the service with name
185 // getServiceNames()[index].
186 void init(size_t index) {
187 mIndex = index;
188 mValid = true;
189 }
190
191public:
192 Cache() = default;
193
194 // Initializes mClient if needed, then returns mClient.
195 // If the service is unavailable but listed in the manifest, this function
196 // will block indefinitely.
197 std::shared_ptr<Codec2Client> getClient() {
198 CHECK(mValid) << "Uninitialized cache";
199 std::scoped_lock lock{mClientMutex};
200 if (!mClient) {
201 mClient = Codec2Client::_CreateFromIndex(mIndex);
202 }
203 return mClient;
204 }
205
206 // Causes a subsequent call to getClient() to create a new client. This
207 // function should be called after the service dies.
208 //
209 // Note: This function is called only by ForAllServices().
210 void invalidate() {
211 CHECK(mValid) << "Uninitialized cache";
212 std::scoped_lock lock{mClientMutex};
213 mClient = nullptr;
214 }
215
216 // Returns a list of traits for components supported by the service. This
217 // list is cached.
218 std::vector<C2Component::Traits> const& getTraits() {
219 CHECK(mValid) << "Uninitialized cache";
220 std::call_once(mTraitsInitializationFlag, [this]() {
221 bool success{false};
222 // Spin until _listComponents() is successful.
223 while (true) {
224 std::shared_ptr<Codec2Client> client = getClient();
225 mTraits = client->_listComponents(&success);
226 if (success) {
227 break;
228 }
229 using namespace std::chrono_literals;
230 static constexpr auto kServiceRetryPeriod = 5s;
231 LOG(INFO) << "Failed to retrieve component traits from service "
232 "\"" << getServiceNames()[mIndex] << "\". "
233 "Retrying...";
234 std::this_thread::sleep_for(kServiceRetryPeriod);
235 }
236 });
237 return mTraits;
238 }
239
240 // List() returns the list of all caches.
241 static std::vector<Cache>& List() {
242 static std::vector<Cache> sCaches{[]() {
243 size_t numServices = getServiceNames().size();
244 std::vector<Cache> caches(numServices);
245 for (size_t i = 0; i < numServices; ++i) {
246 caches[i].init(i);
247 }
248 return caches;
249 }()};
250 return sCaches;
251 }
252};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800253
254// Codec2ConfigurableClient
255
256const C2String& Codec2ConfigurableClient::getName() const {
257 return mName;
258}
259
Pawin Vongmasa36653902018-11-15 00:10:25 -0800260Codec2ConfigurableClient::Codec2ConfigurableClient(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800261 const sp<IConfigurable>& base)
262 : mBase{base},
263 mName{[base]() -> C2String {
264 C2String outName;
265 Return<void> transStatus = base->getName(
266 [&outName](const hidl_string& name) {
267 outName = name.c_str();
268 });
269 return transStatus.isOk() ? outName : "";
270 }()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800271}
272
273c2_status_t Codec2ConfigurableClient::query(
274 const std::vector<C2Param*> &stackParams,
275 const std::vector<C2Param::Index> &heapParamIndices,
276 c2_blocking_t mayBlock,
277 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
278 hidl_vec<ParamIndex> indices(
279 stackParams.size() + heapParamIndices.size());
280 size_t numIndices = 0;
281 for (C2Param* const& stackParam : stackParams) {
282 if (!stackParam) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800283 LOG(WARNING) << "query -- null stack param encountered.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800284 continue;
285 }
286 indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
287 }
288 size_t numStackIndices = numIndices;
289 for (const C2Param::Index& index : heapParamIndices) {
290 indices[numIndices++] =
291 static_cast<ParamIndex>(static_cast<uint32_t>(index));
292 }
293 indices.resize(numIndices);
294 if (heapParams) {
295 heapParams->reserve(heapParams->size() + numIndices);
296 }
297 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800298 Return<void> transStatus = mBase->query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800299 indices,
300 mayBlock == C2_MAY_BLOCK,
301 [&status, &numStackIndices, &stackParams, heapParams](
302 Status s, const Params& p) {
303 status = static_cast<c2_status_t>(s);
304 if (status != C2_OK && status != C2_BAD_INDEX) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800305 LOG(DEBUG) << "query -- call failed: "
306 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800307 return;
308 }
309 std::vector<C2Param*> paramPointers;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800310 if (!parseParamsBlob(&paramPointers, p)) {
311 LOG(ERROR) << "query -- error while parsing params.";
312 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800313 return;
314 }
315 size_t i = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800316 for (auto it = paramPointers.begin();
317 it != paramPointers.end(); ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800318 C2Param* paramPointer = *it;
319 if (numStackIndices > 0) {
320 --numStackIndices;
321 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800322 LOG(WARNING) << "query -- null stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800323 ++it;
324 continue;
325 }
326 for (; i < stackParams.size() && !stackParams[i]; ) {
327 ++i;
328 }
329 if (i >= stackParams.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800330 LOG(ERROR) << "query -- unexpected error.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800331 status = C2_CORRUPTED;
332 return;
333 }
334 if (stackParams[i]->index() != paramPointer->index()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800335 LOG(WARNING) << "query -- param skipped: "
336 "index = "
337 << stackParams[i]->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800338 stackParams[i++]->invalidate();
339 continue;
340 }
341 if (!stackParams[i++]->updateFrom(*paramPointer)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800342 LOG(WARNING) << "query -- param update failed: "
343 "index = "
344 << paramPointer->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800345 }
346 } else {
347 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800348 LOG(WARNING) << "query -- null heap param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800349 ++it;
350 continue;
351 }
352 if (!heapParams) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800353 LOG(WARNING) << "query -- "
354 "unexpected extra stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800355 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800356 heapParams->emplace_back(
357 C2Param::Copy(*paramPointer));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800358 }
359 }
360 ++it;
361 }
362 });
363 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800364 LOG(ERROR) << "query -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800365 return C2_TRANSACTION_FAILED;
366 }
367 return status;
368}
369
370c2_status_t Codec2ConfigurableClient::config(
371 const std::vector<C2Param*> &params,
372 c2_blocking_t mayBlock,
373 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
374 Params hidlParams;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800375 if (!createParamsBlob(&hidlParams, params)) {
376 LOG(ERROR) << "config -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800377 return C2_TRANSACTION_FAILED;
378 }
379 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800380 Return<void> transStatus = mBase->config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800381 hidlParams,
382 mayBlock == C2_MAY_BLOCK,
383 [&status, &params, failures](
384 Status s,
385 const hidl_vec<SettingResult> f,
386 const Params& o) {
387 status = static_cast<c2_status_t>(s);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800388 if (status != C2_OK && status != C2_BAD_INDEX) {
389 LOG(DEBUG) << "config -- call failed: "
390 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800391 }
392 size_t i = failures->size();
393 failures->resize(i + f.size());
394 for (const SettingResult& sf : f) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800395 if (!objcpy(&(*failures)[i++], sf)) {
396 LOG(ERROR) << "config -- "
397 << "invalid SettingResult returned.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800398 return;
399 }
400 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800401 if (!updateParamsFromBlob(params, o)) {
402 LOG(ERROR) << "config -- "
403 << "failed to parse returned params.";
404 status = C2_CORRUPTED;
405 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800406 });
407 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800408 LOG(ERROR) << "config -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800409 return C2_TRANSACTION_FAILED;
410 }
411 return status;
412}
413
414c2_status_t Codec2ConfigurableClient::querySupportedParams(
415 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
416 // TODO: Cache and query properly!
417 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800418 Return<void> transStatus = mBase->querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800419 std::numeric_limits<uint32_t>::min(),
420 std::numeric_limits<uint32_t>::max(),
421 [&status, params](
422 Status s,
423 const hidl_vec<ParamDescriptor>& p) {
424 status = static_cast<c2_status_t>(s);
425 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800426 LOG(DEBUG) << "querySupportedParams -- call failed: "
427 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800428 return;
429 }
430 size_t i = params->size();
431 params->resize(i + p.size());
432 for (const ParamDescriptor& sp : p) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800433 if (!objcpy(&(*params)[i++], sp)) {
434 LOG(ERROR) << "querySupportedParams -- "
435 << "invalid returned ParamDescriptor.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800436 return;
437 }
438 }
439 });
440 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800441 LOG(ERROR) << "querySupportedParams -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800442 return C2_TRANSACTION_FAILED;
443 }
444 return status;
445}
446
447c2_status_t Codec2ConfigurableClient::querySupportedValues(
448 std::vector<C2FieldSupportedValuesQuery>& fields,
449 c2_blocking_t mayBlock) const {
450 hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
451 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800452 if (!objcpy(&inFields[i], fields[i])) {
453 LOG(ERROR) << "querySupportedValues -- bad input";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800454 return C2_TRANSACTION_FAILED;
455 }
456 }
457
458 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800459 Return<void> transStatus = mBase->querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800460 inFields,
461 mayBlock == C2_MAY_BLOCK,
462 [&status, &inFields, &fields](
463 Status s,
464 const hidl_vec<FieldSupportedValuesQueryResult>& r) {
465 status = static_cast<c2_status_t>(s);
466 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800467 LOG(DEBUG) << "querySupportedValues -- call failed: "
468 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800469 return;
470 }
471 if (r.size() != fields.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800472 LOG(ERROR) << "querySupportedValues -- "
473 "input and output lists "
474 "have different sizes.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800475 status = C2_CORRUPTED;
476 return;
477 }
478 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800479 if (!objcpy(&fields[i], inFields[i], r[i])) {
480 LOG(ERROR) << "querySupportedValues -- "
481 "invalid returned value.";
482 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800483 return;
484 }
485 }
486 });
487 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800488 LOG(ERROR) << "querySupportedValues -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800489 return C2_TRANSACTION_FAILED;
490 }
491 return status;
492}
493
494// Codec2Client::Component::HidlListener
495struct Codec2Client::Component::HidlListener : public IComponentListener {
496 std::weak_ptr<Component> component;
497 std::weak_ptr<Listener> base;
498
499 virtual Return<void> onWorkDone(const WorkBundle& workBundle) override {
500 std::list<std::unique_ptr<C2Work>> workItems;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800501 if (!objcpy(&workItems, workBundle)) {
502 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800503 return Void();
504 }
505 // release input buffers potentially held by the component from queue
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800506 std::shared_ptr<Codec2Client::Component> strongComponent =
507 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800508 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800509 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800510 }
511 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800512 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800513 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800514 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800515 }
516 return Void();
517 }
518
519 virtual Return<void> onTripped(
520 const hidl_vec<SettingResult>& settingResults) override {
521 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
522 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800523 for (size_t i = 0; i < settingResults.size(); ++i) {
524 std::unique_ptr<C2SettingResult> c2SettingResult;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800525 if (!objcpy(&c2SettingResult, settingResults[i])) {
526 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800527 return Void();
528 }
529 c2SettingResults[i] = std::move(c2SettingResult);
530 }
531 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
532 listener->onTripped(component, c2SettingResults);
533 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800534 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800535 }
536 return Void();
537 }
538
539 virtual Return<void> onError(Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800540 LOG(DEBUG) << "onError --"
541 << " status = " << s
542 << ", errorCode = " << errorCode
543 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800544 if (std::shared_ptr<Listener> listener = base.lock()) {
545 listener->onError(component, s == Status::OK ?
546 errorCode : static_cast<c2_status_t>(s));
547 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800548 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800549 }
550 return Void();
551 }
552
553 virtual Return<void> onFramesRendered(
554 const hidl_vec<RenderedFrame>& renderedFrames) override {
555 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800556 if (!listener) {
557 LOG(DEBUG) << "onFramesRendered -- listener died.";
558 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800559 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800560 for (const RenderedFrame& renderedFrame : renderedFrames) {
561 listener->onFrameRendered(
562 renderedFrame.bufferQueueId,
563 renderedFrame.slotId,
564 renderedFrame.timestampNs);
565 }
566 return Void();
567 }
568
569 virtual Return<void> onInputBuffersReleased(
570 const hidl_vec<InputBuffer>& inputBuffers) override {
571 std::shared_ptr<Listener> listener = base.lock();
572 if (!listener) {
573 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
574 return Void();
575 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800576 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800577 LOG(VERBOSE) << "onInputBuffersReleased --"
578 " received death notification of"
579 " input buffer:"
580 " frameIndex = " << inputBuffer.frameIndex
581 << ", bufferIndex = " << inputBuffer.arrayIndex
582 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -0800583 listener->onInputBufferDone(
584 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800585 }
586 return Void();
587 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800588
Pawin Vongmasa36653902018-11-15 00:10:25 -0800589};
590
591// Codec2Client
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800592Codec2Client::Codec2Client(const sp<IComponentStore>& base,
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700593 size_t serviceIndex)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800594 : Configurable{
595 [base]() -> sp<IConfigurable> {
596 Return<sp<IConfigurable>> transResult =
597 base->getConfigurable();
598 return transResult.isOk() ?
599 static_cast<sp<IConfigurable>>(transResult) :
600 nullptr;
601 }()
602 },
603 mBase{base},
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700604 mServiceIndex{serviceIndex} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800605 Return<sp<IClientManager>> transResult = base->getPoolClientManager();
606 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800607 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800608 } else {
609 mHostPoolManager = static_cast<sp<IClientManager>>(transResult);
610 }
611}
612
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700613std::string const& Codec2Client::getServiceName() const {
614 return getServiceNames()[mServiceIndex];
615}
616
Pawin Vongmasa36653902018-11-15 00:10:25 -0800617c2_status_t Codec2Client::createComponent(
618 const C2String& name,
619 const std::shared_ptr<Codec2Client::Listener>& listener,
620 std::shared_ptr<Codec2Client::Component>* const component) {
621
Pawin Vongmasa36653902018-11-15 00:10:25 -0800622 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800623 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800624 hidlListener->base = listener;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800625 Return<void> transStatus = mBase->createComponent(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800626 name,
627 hidlListener,
628 ClientManager::getInstance(),
629 [&status, component, hidlListener](
630 Status s,
631 const sp<IComponent>& c) {
632 status = static_cast<c2_status_t>(s);
633 if (status != C2_OK) {
634 return;
635 }
636 *component = std::make_shared<Codec2Client::Component>(c);
637 hidlListener->component = *component;
638 });
639 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800640 LOG(ERROR) << "createComponent(" << name.c_str()
641 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800642 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800643 } else if (status != C2_OK) {
644 LOG(ERROR) << "createComponent(" << name.c_str()
645 << ") -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800646 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800647 } else if (!*component) {
648 LOG(ERROR) << "createComponent(" << name.c_str()
649 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800650 return C2_CORRUPTED;
651 }
652
653 status = (*component)->setDeathListener(*component, listener);
654 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800655 LOG(ERROR) << "createComponent(" << name.c_str()
656 << ") -- failed to set up death listener: "
657 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800658 }
659
660 (*component)->mBufferPoolSender.setReceiver(mHostPoolManager);
661 return status;
662}
663
664c2_status_t Codec2Client::createInterface(
665 const C2String& name,
666 std::shared_ptr<Codec2Client::Interface>* const interface) {
667 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800668 Return<void> transStatus = mBase->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800669 name,
670 [&status, interface](
671 Status s,
672 const sp<IComponentInterface>& i) {
673 status = static_cast<c2_status_t>(s);
674 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800675 return;
676 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800677 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800678 });
679 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800680 LOG(ERROR) << "createInterface(" << name.c_str()
681 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800682 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800683 } else if (status != C2_OK) {
684 LOG(ERROR) << "createComponent(" << name.c_str()
685 << ") -- call failed: " << status << ".";
686 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800687 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800688
Pawin Vongmasa36653902018-11-15 00:10:25 -0800689 return status;
690}
691
692c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800693 std::shared_ptr<InputSurface>* const inputSurface) {
694 c2_status_t status;
695 Return<void> transStatus = mBase->createInputSurface(
696 [&status, inputSurface](
697 Status s,
698 const sp<IInputSurface>& i) {
699 status = static_cast<c2_status_t>(s);
700 if (status != C2_OK) {
701 return;
702 }
703 *inputSurface = std::make_shared<InputSurface>(i);
704 });
705 if (!transStatus.isOk()) {
706 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800707 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800708 } else if (status != C2_OK) {
709 LOG(DEBUG) << "createInputSurface -- call failed: "
710 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800711 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800712 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800713}
714
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700715std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
716 return Cache::List()[mServiceIndex].getTraits();
717}
718
719std::vector<C2Component::Traits> Codec2Client::_listComponents(
720 bool* success) const {
721 std::vector<C2Component::Traits> traits;
722 std::string const& serviceName = getServiceName();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800723 Return<void> transStatus = mBase->listComponents(
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700724 [&traits, &serviceName](Status s,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800725 const hidl_vec<IComponentStore::ComponentTraits>& t) {
726 if (s != Status::OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700727 LOG(DEBUG) << "_listComponents -- call failed: "
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800728 << static_cast<c2_status_t>(s) << ".";
729 return;
730 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700731 traits.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800732 for (size_t i = 0; i < t.size(); ++i) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700733 if (!objcpy(&traits[i], t[i])) {
734 LOG(ERROR) << "_listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800735 return;
736 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700737 traits[i].owner = serviceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800738 }
739 });
740 if (!transStatus.isOk()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700741 LOG(ERROR) << "_listComponents -- transaction failed.";
742 *success = false;
743 } else {
744 *success = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800745 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700746 return traits;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800747}
748
749c2_status_t Codec2Client::copyBuffer(
750 const std::shared_ptr<C2Buffer>& src,
751 const std::shared_ptr<C2Buffer>& dst) {
752 // TODO: Implement?
753 (void)src;
754 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800755 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800756 return C2_OMITTED;
757}
758
759std::shared_ptr<C2ParamReflector>
760 Codec2Client::getParamReflector() {
761 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
762 // should reflect the HAL API.
763 struct SimpleParamReflector : public C2ParamReflector {
764 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
765 hidl_vec<ParamIndex> indices(1);
766 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
767 std::unique_ptr<C2StructDescriptor> descriptor;
768 Return<void> transStatus = mBase->getStructDescriptors(
769 indices,
770 [&descriptor](
771 Status s,
772 const hidl_vec<StructDescriptor>& sd) {
773 c2_status_t status = static_cast<c2_status_t>(s);
774 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800775 LOG(DEBUG) << "SimpleParamReflector -- "
776 "getStructDescriptors() failed: "
777 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800778 descriptor.reset();
779 return;
780 }
781 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800782 LOG(DEBUG) << "SimpleParamReflector -- "
783 "getStructDescriptors() "
784 "returned vector of size "
785 << sd.size() << ". "
786 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800787 descriptor.reset();
788 return;
789 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800790 if (!objcpy(&descriptor, sd[0])) {
791 LOG(DEBUG) << "SimpleParamReflector -- "
792 "getStructDescriptors() returned "
793 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800794 descriptor.reset();
795 return;
796 }
797 });
798 return descriptor;
799 }
800
801 SimpleParamReflector(sp<Base> base)
802 : mBase(base) { }
803
804 sp<Base> mBase;
805 };
806
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800807 return std::make_shared<SimpleParamReflector>(mBase);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800808};
809
810std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700811 const char* name) {
812 size_t index = getServiceIndex(name);
813 return index == getServiceNames().size() ?
814 nullptr : _CreateFromIndex(index);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800815}
816
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700817std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
818 std::string const& name = getServiceNames()[index];
819 LOG(INFO) << "Creating a Codec2 client to service \"" << name << "\"";
820 sp<Base> baseStore = Base::getService(name);
821 CHECK(baseStore) << "Codec2 service \"" << name << "\""
822 " inaccessible for unknown reasons.";
823 LOG(INFO) << "Client to Codec2 service \"" << name << "\" created";
824 return std::make_shared<Codec2Client>(baseStore, index);
825}
826
827c2_status_t Codec2Client::ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800828 const std::string &key,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800829 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
830 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800831 c2_status_t status = C2_NO_INIT; // no IComponentStores present
832
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700833 // Cache the mapping key -> index of Codec2Client in Cache::List().
Pawin Vongmasa36653902018-11-15 00:10:25 -0800834 static std::mutex key2IndexMutex;
835 static std::map<std::string, size_t> key2Index;
836
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800837 // By default try all stores. However, try the last known client first. If
838 // the last known client fails, retry once. We do this by pushing the last
839 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800840 std::deque<size_t> indices;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700841 for (size_t index = Cache::List().size(); index > 0; ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800842 indices.push_front(--index);
843 }
844
845 bool wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700846 {
847 std::scoped_lock lock{key2IndexMutex};
848 auto it = key2Index.find(key);
849 if (it != key2Index.end()) {
850 indices.push_front(it->second);
851 wasMapped = true;
852 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800853 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800854
855 for (size_t index : indices) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700856 Cache& cache = Cache::List()[index];
857 std::shared_ptr<Codec2Client> client{cache.getClient()};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800858 if (client) {
859 status = predicate(client);
860 if (status == C2_OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700861 std::scoped_lock lock{key2IndexMutex};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800862 key2Index[key] = index; // update last known client index
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700863 return C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800864 }
865 }
866 if (wasMapped) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800867 LOG(INFO) << "Could not find \"" << key << "\""
868 " in the last instance. Retrying...";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800869 wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700870 cache.invalidate();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800871 }
872 }
873 return status; // return the last status from a valid client
874}
875
876std::shared_ptr<Codec2Client::Component>
877 Codec2Client::CreateComponentByName(
878 const char* componentName,
879 const std::shared_ptr<Listener>& listener,
880 std::shared_ptr<Codec2Client>* owner) {
881 std::shared_ptr<Component> component;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700882 c2_status_t status = ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800883 componentName,
884 [owner, &component, componentName, &listener](
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800885 const std::shared_ptr<Codec2Client> &client)
886 -> c2_status_t {
887 c2_status_t status = client->createComponent(componentName,
888 listener,
889 &component);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800890 if (status == C2_OK) {
891 if (owner) {
892 *owner = client;
893 }
894 } else if (status != C2_NOT_FOUND) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800895 LOG(DEBUG) << "IComponentStore("
896 << client->getServiceName()
897 << ")::createComponent(\"" << componentName
898 << "\") returned status = "
899 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800900 }
901 return status;
902 });
903 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800904 LOG(DEBUG) << "Could not create component \"" << componentName << "\". "
905 "Status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800906 }
907 return component;
908}
909
910std::shared_ptr<Codec2Client::Interface>
911 Codec2Client::CreateInterfaceByName(
912 const char* interfaceName,
913 std::shared_ptr<Codec2Client>* owner) {
914 std::shared_ptr<Interface> interface;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700915 c2_status_t status = ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800916 interfaceName,
917 [owner, &interface, interfaceName](
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800918 const std::shared_ptr<Codec2Client> &client)
919 -> c2_status_t {
920 c2_status_t status = client->createInterface(interfaceName,
921 &interface);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800922 if (status == C2_OK) {
923 if (owner) {
924 *owner = client;
925 }
926 } else if (status != C2_NOT_FOUND) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800927 LOG(DEBUG) << "IComponentStore("
928 << client->getServiceName()
929 << ")::createInterface(\"" << interfaceName
930 << "\") returned status = "
931 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800932 }
933 return status;
934 });
935 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800936 LOG(DEBUG) << "Could not create interface \"" << interfaceName << "\". "
937 "Status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800938 }
939 return interface;
940}
941
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700942std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
943 static std::vector<C2Component::Traits> sList{[]() {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800944 std::vector<C2Component::Traits> list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700945 for (Cache& cache : Cache::List()) {
946 std::vector<C2Component::Traits> const& traits = cache.getTraits();
947 list.insert(list.end(), traits.begin(), traits.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800948 }
949 return list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700950 }()};
951 return sList;
952}
Pawin Vongmasa36653902018-11-15 00:10:25 -0800953
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700954std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
955 char const* serviceName) {
956 uint32_t inputSurfaceSetting = ::android::base::GetUintProperty(
957 "debug.stagefright.c2inputsurface", uint32_t(0));
958 if (inputSurfaceSetting == 0) {
959 return nullptr;
960 }
961 size_t index = getServiceNames().size();
962 if (serviceName) {
963 index = getServiceIndex(serviceName);
964 if (index == getServiceNames().size()) {
965 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
966 << serviceName << "\"";
967 }
968 }
969
970 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
971 if (index != getServiceNames().size()) {
972 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
973 if (client->createInputSurface(&inputSurface) == C2_OK) {
974 return inputSurface;
975 }
976 }
977 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
978 "from all services...";
979 for (Cache& cache : Cache::List()) {
980 std::shared_ptr<Codec2Client> client = cache.getClient();
981 if (client->createInputSurface(&inputSurface) == C2_OK) {
982 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
983 "service \"" << client->getServiceName() << "\"";
984 return inputSurface;
985 }
986 }
987 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
988 "from all services";
989 return nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800990}
991
992// Codec2Client::Listener
993
994Codec2Client::Listener::~Listener() {
995}
996
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800997// Codec2Client::Interface
998Codec2Client::Interface::Interface(const sp<Base>& base)
999 : Configurable{
1000 [base]() -> sp<IConfigurable> {
1001 Return<sp<IConfigurable>> transResult =
1002 base->getConfigurable();
1003 return transResult.isOk() ?
1004 static_cast<sp<IConfigurable>>(transResult) :
1005 nullptr;
1006 }()
1007 },
1008 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001009}
1010
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001011// Codec2Client::Component
1012Codec2Client::Component::Component(const sp<Base>& base)
1013 : Configurable{
1014 [base]() -> sp<IConfigurable> {
1015 Return<sp<IComponentInterface>> transResult1 =
1016 base->getInterface();
1017 if (!transResult1.isOk()) {
1018 return nullptr;
1019 }
1020 Return<sp<IConfigurable>> transResult2 =
1021 static_cast<sp<IComponentInterface>>(transResult1)->
1022 getConfigurable();
1023 return transResult2.isOk() ?
1024 static_cast<sp<IConfigurable>>(transResult2) :
1025 nullptr;
1026 }()
1027 },
1028 mBase{base},
1029 mBufferPoolSender{nullptr} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001030}
1031
1032Codec2Client::Component::~Component() {
1033}
1034
1035c2_status_t Codec2Client::Component::createBlockPool(
1036 C2Allocator::id_t id,
1037 C2BlockPool::local_id_t* blockPoolId,
1038 std::shared_ptr<Codec2Client::Configurable>* configurable) {
1039 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001040 Return<void> transStatus = mBase->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001041 static_cast<uint32_t>(id),
1042 [&status, blockPoolId, configurable](
1043 Status s,
1044 uint64_t pId,
1045 const sp<IConfigurable>& c) {
1046 status = static_cast<c2_status_t>(s);
1047 configurable->reset();
1048 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001049 LOG(DEBUG) << "createBlockPool -- call failed: "
1050 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001051 return;
1052 }
1053 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001054 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001055 });
1056 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001057 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001058 return C2_TRANSACTION_FAILED;
1059 }
1060 return status;
1061}
1062
1063c2_status_t Codec2Client::Component::destroyBlockPool(
1064 C2BlockPool::local_id_t localId) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001065 Return<Status> transResult = mBase->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001066 static_cast<uint64_t>(localId));
1067 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001068 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001069 return C2_TRANSACTION_FAILED;
1070 }
1071 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1072}
1073
Wonsik Kimab34ed62019-01-31 15:28:46 -08001074void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001075 const std::list<std::unique_ptr<C2Work>> &workItems) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001076 // Output bufferqueue-based blocks' lifetime management
1077 mOutputBufferQueueMutex.lock();
1078 sp<IGraphicBufferProducer> igbp = mOutputIgbp;
1079 uint64_t bqId = mOutputBqId;
1080 uint32_t generation = mOutputGeneration;
1081 mOutputBufferQueueMutex.unlock();
1082
1083 if (igbp) {
1084 holdBufferQueueBlocks(workItems, igbp, bqId, generation);
1085 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001086}
1087
1088c2_status_t Codec2Client::Component::queue(
1089 std::list<std::unique_ptr<C2Work>>* const items) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001090 WorkBundle workBundle;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001091 if (!objcpy(&workBundle, *items, &mBufferPoolSender)) {
1092 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001093 return C2_TRANSACTION_FAILED;
1094 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001095 Return<Status> transStatus = mBase->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001096 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001097 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001098 return C2_TRANSACTION_FAILED;
1099 }
1100 c2_status_t status =
1101 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1102 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001103 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001104 }
1105 return status;
1106}
1107
1108c2_status_t Codec2Client::Component::flush(
1109 C2Component::flush_mode_t mode,
1110 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
1111 (void)mode; // Flush mode isn't supported in HIDL yet.
1112 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001113 Return<void> transStatus = mBase->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001114 [&status, flushedWork](
1115 Status s, const WorkBundle& wb) {
1116 status = static_cast<c2_status_t>(s);
1117 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001118 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001119 return;
1120 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001121 if (!objcpy(flushedWork, wb)) {
1122 status = C2_CORRUPTED;
1123 } else {
1124 status = C2_OK;
1125 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001126 });
1127 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001128 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001129 return C2_TRANSACTION_FAILED;
1130 }
1131
1132 // Indices of flushed work items.
1133 std::vector<uint64_t> flushedIndices;
1134 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
1135 if (work) {
1136 if (work->worklets.empty()
1137 || !work->worklets.back()
1138 || (work->worklets.back()->output.flags &
1139 C2FrameData::FLAG_INCOMPLETE) == 0) {
1140 // input is complete
1141 flushedIndices.emplace_back(
1142 work->input.ordinal.frameIndex.peeku());
1143 }
1144 }
1145 }
1146
Pawin Vongmasa36653902018-11-15 00:10:25 -08001147 // Output bufferqueue-based blocks' lifetime management
1148 mOutputBufferQueueMutex.lock();
1149 sp<IGraphicBufferProducer> igbp = mOutputIgbp;
1150 uint64_t bqId = mOutputBqId;
1151 uint32_t generation = mOutputGeneration;
1152 mOutputBufferQueueMutex.unlock();
1153
1154 if (igbp) {
1155 holdBufferQueueBlocks(*flushedWork, igbp, bqId, generation);
1156 }
1157
1158 return status;
1159}
1160
1161c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001162 Return<Status> transStatus = mBase->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001163 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1164 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001165 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001166 return C2_TRANSACTION_FAILED;
1167 }
1168 c2_status_t status =
1169 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1170 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001171 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001172 }
1173 return status;
1174}
1175
1176c2_status_t Codec2Client::Component::start() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001177 Return<Status> transStatus = mBase->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001178 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001179 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001180 return C2_TRANSACTION_FAILED;
1181 }
1182 c2_status_t status =
1183 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1184 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001185 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001186 }
1187 return status;
1188}
1189
1190c2_status_t Codec2Client::Component::stop() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001191 Return<Status> transStatus = mBase->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001192 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001193 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001194 return C2_TRANSACTION_FAILED;
1195 }
1196 c2_status_t status =
1197 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1198 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001199 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001200 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001201 return status;
1202}
1203
1204c2_status_t Codec2Client::Component::reset() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001205 Return<Status> transStatus = mBase->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001206 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001207 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001208 return C2_TRANSACTION_FAILED;
1209 }
1210 c2_status_t status =
1211 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1212 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001213 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001214 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001215 return status;
1216}
1217
1218c2_status_t Codec2Client::Component::release() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001219 Return<Status> transStatus = mBase->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001220 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001221 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001222 return C2_TRANSACTION_FAILED;
1223 }
1224 c2_status_t status =
1225 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1226 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001227 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001228 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001229 return status;
1230}
1231
1232c2_status_t Codec2Client::Component::setOutputSurface(
1233 C2BlockPool::local_id_t blockPoolId,
1234 const sp<IGraphicBufferProducer>& surface,
1235 uint32_t generation) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001236 sp<HGraphicBufferProducer2> igbp =
1237 surface->getHalInterface<HGraphicBufferProducer2>();
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08001238
Pawin Vongmasa36653902018-11-15 00:10:25 -08001239 if (!igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001240 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001241 }
1242
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001243 Return<Status> transStatus = mBase->setOutputSurface(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001244 static_cast<uint64_t>(blockPoolId), igbp);
1245 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001246 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001247 return C2_TRANSACTION_FAILED;
1248 }
1249 c2_status_t status =
1250 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1251 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001252 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001253 } else {
1254 std::lock_guard<std::mutex> lock(mOutputBufferQueueMutex);
1255 if (mOutputIgbp != surface) {
1256 mOutputIgbp = surface;
1257 if (!surface) {
1258 mOutputBqId = 0;
1259 } else if (surface->getUniqueId(&mOutputBqId) != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001260 LOG(ERROR) << "setOutputSurface -- "
1261 "cannot obtain bufferqueue id.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001262 }
1263 }
1264 mOutputGeneration = generation;
1265 }
1266 return status;
1267}
1268
1269status_t Codec2Client::Component::queueToOutputSurface(
1270 const C2ConstGraphicBlock& block,
1271 const QueueBufferInput& input,
1272 QueueBufferOutput* output) {
1273 uint32_t generation;
1274 uint64_t bqId;
1275 int32_t bqSlot;
1276 if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot) ||
1277 bqId == 0) {
1278 // Block not from bufferqueue -- it must be attached before queuing.
1279
1280 mOutputBufferQueueMutex.lock();
1281 sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp;
1282 uint32_t outputGeneration = mOutputGeneration;
1283 mOutputBufferQueueMutex.unlock();
1284
Sungtak Lee9b148812019-01-27 16:30:13 -08001285 status_t status = attachToBufferQueue(block,
Pawin Vongmasa36653902018-11-15 00:10:25 -08001286 outputIgbp,
1287 outputGeneration,
1288 &bqSlot);
1289 if (status != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001290 LOG(WARNING) << "queueToOutputSurface -- attaching failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001291 return INVALID_OPERATION;
1292 }
1293
1294 status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
1295 input, output);
1296 if (status != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001297 LOG(ERROR) << "queueToOutputSurface -- queueBuffer() failed "
1298 "on non-bufferqueue-based block. "
1299 "Error = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001300 return status;
1301 }
1302 return OK;
1303 }
1304
1305 mOutputBufferQueueMutex.lock();
1306 sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp;
1307 uint64_t outputBqId = mOutputBqId;
1308 uint32_t outputGeneration = mOutputGeneration;
1309 mOutputBufferQueueMutex.unlock();
1310
1311 if (!outputIgbp) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001312 LOG(VERBOSE) << "queueToOutputSurface -- output surface is null.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001313 return NO_INIT;
1314 }
1315
Sungtak Lee9b148812019-01-27 16:30:13 -08001316 if (bqId != outputBqId || generation != outputGeneration) {
1317 if (!holdBufferQueueBlock(block, mOutputIgbp, mOutputBqId, mOutputGeneration)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001318 LOG(ERROR) << "queueToOutputSurface -- migration failed.";
Sungtak Lee9b148812019-01-27 16:30:13 -08001319 return DEAD_OBJECT;
1320 }
1321 if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001322 LOG(ERROR) << "queueToOutputSurface -- corrupted bufferqueue assignment.";
Sungtak Lee9b148812019-01-27 16:30:13 -08001323 return UNKNOWN_ERROR;
1324 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001325 }
1326
1327 status_t status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
1328 input, output);
1329 if (status != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001330 LOG(DEBUG) << "queueToOutputSurface -- queueBuffer() failed "
1331 "on bufferqueue-based block. "
1332 "Error = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001333 return status;
1334 }
1335 if (!yieldBufferQueueBlock(block)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001336 LOG(DEBUG) << "queueToOutputSurface -- cannot yield "
1337 "bufferqueue-based block to the bufferqueue.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001338 return UNKNOWN_ERROR;
1339 }
1340 return OK;
1341}
1342
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001343c2_status_t Codec2Client::Component::connectToInputSurface(
1344 const std::shared_ptr<InputSurface>& inputSurface,
1345 std::shared_ptr<InputSurfaceConnection>* connection) {
1346 c2_status_t status;
1347 Return<void> transStatus = mBase->connectToInputSurface(
1348 inputSurface->mBase,
1349 [&status, connection](
1350 Status s, const sp<IInputSurfaceConnection>& c) {
1351 status = static_cast<c2_status_t>(s);
1352 if (status != C2_OK) {
1353 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1354 << status << ".";
1355 return;
1356 }
1357 *connection = std::make_shared<InputSurfaceConnection>(c);
1358 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001359 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001360 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001361 return C2_TRANSACTION_FAILED;
1362 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001363 return status;
1364}
1365
1366c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001367 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001368 const sp<HGraphicBufferSource>& source,
1369 std::shared_ptr<InputSurfaceConnection>* connection) {
1370 c2_status_t status;
1371 Return<void> transStatus = mBase->connectToOmxInputSurface(
1372 producer, source,
1373 [&status, connection](
1374 Status s, const sp<IInputSurfaceConnection>& c) {
1375 status = static_cast<c2_status_t>(s);
1376 if (status != C2_OK) {
1377 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1378 << status << ".";
1379 return;
1380 }
1381 *connection = std::make_shared<InputSurfaceConnection>(c);
1382 });
1383 if (!transStatus.isOk()) {
1384 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1385 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001386 }
1387 return status;
1388}
1389
1390c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001391 Return<Status> transStatus = mBase->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001392 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001393 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001394 return C2_TRANSACTION_FAILED;
1395 }
1396 c2_status_t status =
1397 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1398 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001399 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1400 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001401 }
1402 return status;
1403}
1404
1405c2_status_t Codec2Client::Component::setDeathListener(
1406 const std::shared_ptr<Component>& component,
1407 const std::shared_ptr<Listener>& listener) {
1408
1409 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1410 std::weak_ptr<Component> component;
1411 std::weak_ptr<Listener> base;
1412
1413 virtual void serviceDied(
1414 uint64_t /* cookie */,
1415 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1416 ) override {
1417 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1418 listener->onDeath(component);
1419 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001420 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001421 }
1422 }
1423 };
1424
1425 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1426 deathRecipient->base = listener;
1427 deathRecipient->component = component;
1428
1429 component->mDeathRecipient = deathRecipient;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001430 Return<bool> transResult = component->mBase->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001431 component->mDeathRecipient, 0);
1432 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001433 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001434 return C2_TRANSACTION_FAILED;
1435 }
1436 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001437 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001438 return C2_CORRUPTED;
1439 }
1440 return C2_OK;
1441}
1442
1443// Codec2Client::InputSurface
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001444Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base)
1445 : Configurable{
1446 [base]() -> sp<IConfigurable> {
1447 Return<sp<IConfigurable>> transResult =
1448 base->getConfigurable();
1449 return transResult.isOk() ?
1450 static_cast<sp<IConfigurable>>(transResult) :
1451 nullptr;
1452 }()
1453 },
1454 mBase{base},
1455 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001456 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
1457 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001458 base->getGraphicBufferProducer();
1459 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001460 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001461 nullptr;
1462 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001463}
1464
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001465sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08001466 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1467 return mGraphicBufferProducer;
1468}
1469
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001470sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001471 return mBase;
1472}
1473
1474// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08001475Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001476 const sp<IInputSurfaceConnection>& base)
1477 : Configurable{
1478 [base]() -> sp<IConfigurable> {
1479 Return<sp<IConfigurable>> transResult =
1480 base->getConfigurable();
1481 return transResult.isOk() ?
1482 static_cast<sp<IConfigurable>>(transResult) :
1483 nullptr;
1484 }()
1485 },
1486 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001487}
1488
1489c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001490 Return<Status> transResult = mBase->disconnect();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001491 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1492}
1493
1494} // namespace android
1495