blob: c747190397379c78fe2ee8751f99cc7c8f2e114b [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 }
Pawin Vongmasa54782cf2019-10-09 02:15:50 -0700128 CHECK(mClient) << "Failed to create Codec2Client to service \""
129 << GetServiceNames()[mIndex] << "\". (Index = "
130 << mIndex << ").";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700131 return mClient;
132 }
133
134 // Causes a subsequent call to getClient() to create a new client. This
135 // function should be called after the service dies.
136 //
137 // Note: This function is called only by ForAllServices().
138 void invalidate() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700139 std::scoped_lock lock{mClientMutex};
140 mClient = nullptr;
141 }
142
143 // Returns a list of traits for components supported by the service. This
144 // list is cached.
145 std::vector<C2Component::Traits> const& getTraits() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700146 std::call_once(mTraitsInitializationFlag, [this]() {
147 bool success{false};
148 // Spin until _listComponents() is successful.
149 while (true) {
150 std::shared_ptr<Codec2Client> client = getClient();
151 mTraits = client->_listComponents(&success);
152 if (success) {
153 break;
154 }
155 using namespace std::chrono_literals;
156 static constexpr auto kServiceRetryPeriod = 5s;
157 LOG(INFO) << "Failed to retrieve component traits from service "
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700158 "\"" << GetServiceNames()[mIndex] << "\". "
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700159 "Retrying...";
160 std::this_thread::sleep_for(kServiceRetryPeriod);
161 }
162 });
163 return mTraits;
164 }
165
166 // List() returns the list of all caches.
167 static std::vector<Cache>& List() {
168 static std::vector<Cache> sCaches{[]() {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700169 size_t numServices = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700170 std::vector<Cache> caches(numServices);
171 for (size_t i = 0; i < numServices; ++i) {
172 caches[i].init(i);
173 }
174 return caches;
175 }()};
176 return sCaches;
177 }
178};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800179
180// Codec2ConfigurableClient
181
182const C2String& Codec2ConfigurableClient::getName() const {
183 return mName;
184}
185
Pawin Vongmasa36653902018-11-15 00:10:25 -0800186Codec2ConfigurableClient::Codec2ConfigurableClient(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800187 const sp<IConfigurable>& base)
188 : mBase{base},
189 mName{[base]() -> C2String {
190 C2String outName;
191 Return<void> transStatus = base->getName(
192 [&outName](const hidl_string& name) {
193 outName = name.c_str();
194 });
195 return transStatus.isOk() ? outName : "";
196 }()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800197}
198
199c2_status_t Codec2ConfigurableClient::query(
200 const std::vector<C2Param*> &stackParams,
201 const std::vector<C2Param::Index> &heapParamIndices,
202 c2_blocking_t mayBlock,
203 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
204 hidl_vec<ParamIndex> indices(
205 stackParams.size() + heapParamIndices.size());
206 size_t numIndices = 0;
207 for (C2Param* const& stackParam : stackParams) {
208 if (!stackParam) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800209 LOG(WARNING) << "query -- null stack param encountered.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800210 continue;
211 }
212 indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
213 }
214 size_t numStackIndices = numIndices;
215 for (const C2Param::Index& index : heapParamIndices) {
216 indices[numIndices++] =
217 static_cast<ParamIndex>(static_cast<uint32_t>(index));
218 }
219 indices.resize(numIndices);
220 if (heapParams) {
221 heapParams->reserve(heapParams->size() + numIndices);
222 }
223 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800224 Return<void> transStatus = mBase->query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800225 indices,
226 mayBlock == C2_MAY_BLOCK,
227 [&status, &numStackIndices, &stackParams, heapParams](
228 Status s, const Params& p) {
229 status = static_cast<c2_status_t>(s);
230 if (status != C2_OK && status != C2_BAD_INDEX) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800231 LOG(DEBUG) << "query -- call failed: "
232 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800233 return;
234 }
235 std::vector<C2Param*> paramPointers;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800236 if (!parseParamsBlob(&paramPointers, p)) {
237 LOG(ERROR) << "query -- error while parsing params.";
238 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800239 return;
240 }
241 size_t i = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800242 for (auto it = paramPointers.begin();
243 it != paramPointers.end(); ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800244 C2Param* paramPointer = *it;
245 if (numStackIndices > 0) {
246 --numStackIndices;
247 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800248 LOG(WARNING) << "query -- null stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800249 ++it;
250 continue;
251 }
252 for (; i < stackParams.size() && !stackParams[i]; ) {
253 ++i;
254 }
255 if (i >= stackParams.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800256 LOG(ERROR) << "query -- unexpected error.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800257 status = C2_CORRUPTED;
258 return;
259 }
260 if (stackParams[i]->index() != paramPointer->index()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800261 LOG(WARNING) << "query -- param skipped: "
262 "index = "
263 << stackParams[i]->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800264 stackParams[i++]->invalidate();
265 continue;
266 }
267 if (!stackParams[i++]->updateFrom(*paramPointer)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800268 LOG(WARNING) << "query -- param update failed: "
269 "index = "
270 << paramPointer->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800271 }
272 } else {
273 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800274 LOG(WARNING) << "query -- null heap param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800275 ++it;
276 continue;
277 }
278 if (!heapParams) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800279 LOG(WARNING) << "query -- "
280 "unexpected extra stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800281 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800282 heapParams->emplace_back(
283 C2Param::Copy(*paramPointer));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800284 }
285 }
286 ++it;
287 }
288 });
289 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800290 LOG(ERROR) << "query -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800291 return C2_TRANSACTION_FAILED;
292 }
293 return status;
294}
295
296c2_status_t Codec2ConfigurableClient::config(
297 const std::vector<C2Param*> &params,
298 c2_blocking_t mayBlock,
299 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
300 Params hidlParams;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800301 if (!createParamsBlob(&hidlParams, params)) {
302 LOG(ERROR) << "config -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800303 return C2_TRANSACTION_FAILED;
304 }
305 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800306 Return<void> transStatus = mBase->config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800307 hidlParams,
308 mayBlock == C2_MAY_BLOCK,
309 [&status, &params, failures](
310 Status s,
311 const hidl_vec<SettingResult> f,
312 const Params& o) {
313 status = static_cast<c2_status_t>(s);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800314 if (status != C2_OK && status != C2_BAD_INDEX) {
315 LOG(DEBUG) << "config -- call failed: "
316 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800317 }
318 size_t i = failures->size();
319 failures->resize(i + f.size());
320 for (const SettingResult& sf : f) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800321 if (!objcpy(&(*failures)[i++], sf)) {
322 LOG(ERROR) << "config -- "
323 << "invalid SettingResult returned.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800324 return;
325 }
326 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800327 if (!updateParamsFromBlob(params, o)) {
328 LOG(ERROR) << "config -- "
329 << "failed to parse returned params.";
330 status = C2_CORRUPTED;
331 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800332 });
333 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800334 LOG(ERROR) << "config -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800335 return C2_TRANSACTION_FAILED;
336 }
337 return status;
338}
339
340c2_status_t Codec2ConfigurableClient::querySupportedParams(
341 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
342 // TODO: Cache and query properly!
343 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800344 Return<void> transStatus = mBase->querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800345 std::numeric_limits<uint32_t>::min(),
346 std::numeric_limits<uint32_t>::max(),
347 [&status, params](
348 Status s,
349 const hidl_vec<ParamDescriptor>& p) {
350 status = static_cast<c2_status_t>(s);
351 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800352 LOG(DEBUG) << "querySupportedParams -- call failed: "
353 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800354 return;
355 }
356 size_t i = params->size();
357 params->resize(i + p.size());
358 for (const ParamDescriptor& sp : p) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800359 if (!objcpy(&(*params)[i++], sp)) {
360 LOG(ERROR) << "querySupportedParams -- "
361 << "invalid returned ParamDescriptor.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800362 return;
363 }
364 }
365 });
366 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800367 LOG(ERROR) << "querySupportedParams -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800368 return C2_TRANSACTION_FAILED;
369 }
370 return status;
371}
372
373c2_status_t Codec2ConfigurableClient::querySupportedValues(
374 std::vector<C2FieldSupportedValuesQuery>& fields,
375 c2_blocking_t mayBlock) const {
376 hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
377 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800378 if (!objcpy(&inFields[i], fields[i])) {
379 LOG(ERROR) << "querySupportedValues -- bad input";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800380 return C2_TRANSACTION_FAILED;
381 }
382 }
383
384 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800385 Return<void> transStatus = mBase->querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800386 inFields,
387 mayBlock == C2_MAY_BLOCK,
388 [&status, &inFields, &fields](
389 Status s,
390 const hidl_vec<FieldSupportedValuesQueryResult>& r) {
391 status = static_cast<c2_status_t>(s);
392 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800393 LOG(DEBUG) << "querySupportedValues -- call failed: "
394 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800395 return;
396 }
397 if (r.size() != fields.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800398 LOG(ERROR) << "querySupportedValues -- "
399 "input and output lists "
400 "have different sizes.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800401 status = C2_CORRUPTED;
402 return;
403 }
404 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800405 if (!objcpy(&fields[i], inFields[i], r[i])) {
406 LOG(ERROR) << "querySupportedValues -- "
407 "invalid returned value.";
408 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800409 return;
410 }
411 }
412 });
413 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800414 LOG(ERROR) << "querySupportedValues -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800415 return C2_TRANSACTION_FAILED;
416 }
417 return status;
418}
419
420// Codec2Client::Component::HidlListener
421struct Codec2Client::Component::HidlListener : public IComponentListener {
422 std::weak_ptr<Component> component;
423 std::weak_ptr<Listener> base;
424
425 virtual Return<void> onWorkDone(const WorkBundle& workBundle) override {
426 std::list<std::unique_ptr<C2Work>> workItems;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800427 if (!objcpy(&workItems, workBundle)) {
428 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800429 return Void();
430 }
431 // release input buffers potentially held by the component from queue
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800432 std::shared_ptr<Codec2Client::Component> strongComponent =
433 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800434 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800435 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800436 }
437 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800438 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800439 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800440 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800441 }
442 return Void();
443 }
444
445 virtual Return<void> onTripped(
446 const hidl_vec<SettingResult>& settingResults) override {
447 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
448 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800449 for (size_t i = 0; i < settingResults.size(); ++i) {
450 std::unique_ptr<C2SettingResult> c2SettingResult;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800451 if (!objcpy(&c2SettingResult, settingResults[i])) {
452 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800453 return Void();
454 }
455 c2SettingResults[i] = std::move(c2SettingResult);
456 }
457 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
458 listener->onTripped(component, c2SettingResults);
459 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800460 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800461 }
462 return Void();
463 }
464
465 virtual Return<void> onError(Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800466 LOG(DEBUG) << "onError --"
467 << " status = " << s
468 << ", errorCode = " << errorCode
469 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800470 if (std::shared_ptr<Listener> listener = base.lock()) {
471 listener->onError(component, s == Status::OK ?
472 errorCode : static_cast<c2_status_t>(s));
473 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800474 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800475 }
476 return Void();
477 }
478
479 virtual Return<void> onFramesRendered(
480 const hidl_vec<RenderedFrame>& renderedFrames) override {
481 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800482 if (!listener) {
483 LOG(DEBUG) << "onFramesRendered -- listener died.";
484 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800485 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800486 for (const RenderedFrame& renderedFrame : renderedFrames) {
487 listener->onFrameRendered(
488 renderedFrame.bufferQueueId,
489 renderedFrame.slotId,
490 renderedFrame.timestampNs);
491 }
492 return Void();
493 }
494
495 virtual Return<void> onInputBuffersReleased(
496 const hidl_vec<InputBuffer>& inputBuffers) override {
497 std::shared_ptr<Listener> listener = base.lock();
498 if (!listener) {
499 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
500 return Void();
501 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800502 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800503 LOG(VERBOSE) << "onInputBuffersReleased --"
504 " received death notification of"
505 " input buffer:"
506 " frameIndex = " << inputBuffer.frameIndex
507 << ", bufferIndex = " << inputBuffer.arrayIndex
508 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -0800509 listener->onInputBufferDone(
510 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800511 }
512 return Void();
513 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800514
Pawin Vongmasa36653902018-11-15 00:10:25 -0800515};
516
517// Codec2Client
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800518Codec2Client::Codec2Client(const sp<IComponentStore>& base,
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700519 size_t serviceIndex)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800520 : Configurable{
521 [base]() -> sp<IConfigurable> {
522 Return<sp<IConfigurable>> transResult =
523 base->getConfigurable();
524 return transResult.isOk() ?
525 static_cast<sp<IConfigurable>>(transResult) :
526 nullptr;
527 }()
528 },
529 mBase{base},
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700530 mServiceIndex{serviceIndex} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800531 Return<sp<IClientManager>> transResult = base->getPoolClientManager();
532 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800533 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800534 } else {
535 mHostPoolManager = static_cast<sp<IClientManager>>(transResult);
536 }
537}
538
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700539sp<Codec2Client::Base> const& Codec2Client::getBase() const {
540 return mBase;
541}
542
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700543std::string const& Codec2Client::getServiceName() const {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700544 return GetServiceNames()[mServiceIndex];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700545}
546
Pawin Vongmasa36653902018-11-15 00:10:25 -0800547c2_status_t Codec2Client::createComponent(
548 const C2String& name,
549 const std::shared_ptr<Codec2Client::Listener>& listener,
550 std::shared_ptr<Codec2Client::Component>* const component) {
551
Pawin Vongmasa36653902018-11-15 00:10:25 -0800552 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800553 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800554 hidlListener->base = listener;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800555 Return<void> transStatus = mBase->createComponent(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800556 name,
557 hidlListener,
558 ClientManager::getInstance(),
559 [&status, component, hidlListener](
560 Status s,
561 const sp<IComponent>& c) {
562 status = static_cast<c2_status_t>(s);
563 if (status != C2_OK) {
564 return;
565 }
566 *component = std::make_shared<Codec2Client::Component>(c);
567 hidlListener->component = *component;
568 });
569 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800570 LOG(ERROR) << "createComponent(" << name.c_str()
571 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800572 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800573 } else if (status != C2_OK) {
574 LOG(ERROR) << "createComponent(" << name.c_str()
575 << ") -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800576 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800577 } else if (!*component) {
578 LOG(ERROR) << "createComponent(" << name.c_str()
579 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800580 return C2_CORRUPTED;
581 }
582
583 status = (*component)->setDeathListener(*component, listener);
584 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800585 LOG(ERROR) << "createComponent(" << name.c_str()
586 << ") -- failed to set up death listener: "
587 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800588 }
589
590 (*component)->mBufferPoolSender.setReceiver(mHostPoolManager);
591 return status;
592}
593
594c2_status_t Codec2Client::createInterface(
595 const C2String& name,
596 std::shared_ptr<Codec2Client::Interface>* const interface) {
597 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800598 Return<void> transStatus = mBase->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800599 name,
600 [&status, interface](
601 Status s,
602 const sp<IComponentInterface>& i) {
603 status = static_cast<c2_status_t>(s);
604 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800605 return;
606 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800607 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800608 });
609 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800610 LOG(ERROR) << "createInterface(" << name.c_str()
611 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800612 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800613 } else if (status != C2_OK) {
614 LOG(ERROR) << "createComponent(" << name.c_str()
615 << ") -- call failed: " << status << ".";
616 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800617 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800618
Pawin Vongmasa36653902018-11-15 00:10:25 -0800619 return status;
620}
621
622c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800623 std::shared_ptr<InputSurface>* const inputSurface) {
624 c2_status_t status;
625 Return<void> transStatus = mBase->createInputSurface(
626 [&status, inputSurface](
627 Status s,
628 const sp<IInputSurface>& i) {
629 status = static_cast<c2_status_t>(s);
630 if (status != C2_OK) {
631 return;
632 }
633 *inputSurface = std::make_shared<InputSurface>(i);
634 });
635 if (!transStatus.isOk()) {
636 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800637 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800638 } else if (status != C2_OK) {
639 LOG(DEBUG) << "createInputSurface -- call failed: "
640 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800641 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800642 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800643}
644
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700645std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
646 return Cache::List()[mServiceIndex].getTraits();
647}
648
649std::vector<C2Component::Traits> Codec2Client::_listComponents(
650 bool* success) const {
651 std::vector<C2Component::Traits> traits;
652 std::string const& serviceName = getServiceName();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800653 Return<void> transStatus = mBase->listComponents(
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700654 [&traits, &serviceName](Status s,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800655 const hidl_vec<IComponentStore::ComponentTraits>& t) {
656 if (s != Status::OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700657 LOG(DEBUG) << "_listComponents -- call failed: "
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800658 << static_cast<c2_status_t>(s) << ".";
659 return;
660 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700661 traits.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800662 for (size_t i = 0; i < t.size(); ++i) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700663 if (!objcpy(&traits[i], t[i])) {
664 LOG(ERROR) << "_listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800665 return;
666 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700667 traits[i].owner = serviceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800668 }
669 });
670 if (!transStatus.isOk()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700671 LOG(ERROR) << "_listComponents -- transaction failed.";
672 *success = false;
673 } else {
674 *success = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800675 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700676 return traits;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800677}
678
679c2_status_t Codec2Client::copyBuffer(
680 const std::shared_ptr<C2Buffer>& src,
681 const std::shared_ptr<C2Buffer>& dst) {
682 // TODO: Implement?
683 (void)src;
684 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800685 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800686 return C2_OMITTED;
687}
688
689std::shared_ptr<C2ParamReflector>
690 Codec2Client::getParamReflector() {
691 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
692 // should reflect the HAL API.
693 struct SimpleParamReflector : public C2ParamReflector {
694 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
695 hidl_vec<ParamIndex> indices(1);
696 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
697 std::unique_ptr<C2StructDescriptor> descriptor;
698 Return<void> transStatus = mBase->getStructDescriptors(
699 indices,
700 [&descriptor](
701 Status s,
702 const hidl_vec<StructDescriptor>& sd) {
703 c2_status_t status = static_cast<c2_status_t>(s);
704 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800705 LOG(DEBUG) << "SimpleParamReflector -- "
706 "getStructDescriptors() failed: "
707 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800708 descriptor.reset();
709 return;
710 }
711 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800712 LOG(DEBUG) << "SimpleParamReflector -- "
713 "getStructDescriptors() "
714 "returned vector of size "
715 << sd.size() << ". "
716 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800717 descriptor.reset();
718 return;
719 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800720 if (!objcpy(&descriptor, sd[0])) {
721 LOG(DEBUG) << "SimpleParamReflector -- "
722 "getStructDescriptors() returned "
723 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800724 descriptor.reset();
725 return;
726 }
727 });
728 return descriptor;
729 }
730
731 SimpleParamReflector(sp<Base> base)
732 : mBase(base) { }
733
734 sp<Base> mBase;
735 };
736
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800737 return std::make_shared<SimpleParamReflector>(mBase);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800738};
739
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700740std::vector<std::string> const& Codec2Client::GetServiceNames() {
741 static std::vector<std::string> sServiceNames{[]() {
742 using ::android::hardware::media::c2::V1_0::IComponentStore;
743 using ::android::hidl::manager::V1_2::IServiceManager;
744
745 while (true) {
746 sp<IServiceManager> serviceManager = IServiceManager::getService();
747 CHECK(serviceManager) << "Hardware service manager is not running.";
748
749 // There are three categories of services based on names.
750 std::vector<std::string> defaultNames; // Prefixed with "default"
751 std::vector<std::string> vendorNames; // Prefixed with "vendor"
752 std::vector<std::string> otherNames; // Others
753 Return<void> transResult;
754 transResult = serviceManager->listManifestByInterface(
755 IComponentStore::descriptor,
756 [&defaultNames, &vendorNames, &otherNames](
757 hidl_vec<hidl_string> const& instanceNames) {
758 for (hidl_string const& instanceName : instanceNames) {
759 char const* name = instanceName.c_str();
760 if (strncmp(name, "default", 7) == 0) {
761 defaultNames.emplace_back(name);
762 } else if (strncmp(name, "vendor", 6) == 0) {
763 vendorNames.emplace_back(name);
764 } else {
765 otherNames.emplace_back(name);
766 }
767 }
768 });
769 if (transResult.isOk()) {
770 // Sort service names in each category.
771 std::sort(defaultNames.begin(), defaultNames.end());
772 std::sort(vendorNames.begin(), vendorNames.end());
773 std::sort(otherNames.begin(), otherNames.end());
774
775 // Concatenate the three lists in this order: default, vendor,
776 // other.
777 std::vector<std::string>& names = defaultNames;
778 names.reserve(names.size() + vendorNames.size() + otherNames.size());
779 names.insert(names.end(),
780 std::make_move_iterator(vendorNames.begin()),
781 std::make_move_iterator(vendorNames.end()));
782 names.insert(names.end(),
783 std::make_move_iterator(otherNames.begin()),
784 std::make_move_iterator(otherNames.end()));
785
786 // Summarize to logcat.
787 if (names.empty()) {
788 LOG(INFO) << "No Codec2 services declared in the manifest.";
789 } else {
790 std::stringstream stringOutput;
791 stringOutput << "Available Codec2 services:";
792 for (std::string const& name : names) {
793 stringOutput << " \"" << name << "\"";
794 }
795 LOG(INFO) << stringOutput.str();
796 }
797
798 return names;
799 }
800 LOG(ERROR) << "Could not retrieve the list of service instances of "
801 << IComponentStore::descriptor
802 << ". Retrying...";
803 }
804 }()};
805 return sServiceNames;
806}
807
Pawin Vongmasa36653902018-11-15 00:10:25 -0800808std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700809 const char* name) {
810 size_t index = getServiceIndex(name);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700811 return index == GetServiceNames().size() ?
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700812 nullptr : _CreateFromIndex(index);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800813}
814
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700815std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
816 CreateFromAllServices() {
817 std::vector<std::shared_ptr<Codec2Client>> clients(
818 GetServiceNames().size());
819 for (size_t i = GetServiceNames().size(); i > 0; ) {
820 --i;
821 clients[i] = _CreateFromIndex(i);
822 }
823 return clients;
824}
825
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700826std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700827 std::string const& name = GetServiceNames()[index];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700828 LOG(INFO) << "Creating a Codec2 client to service \"" << name << "\"";
829 sp<Base> baseStore = Base::getService(name);
830 CHECK(baseStore) << "Codec2 service \"" << name << "\""
831 " inaccessible for unknown reasons.";
832 LOG(INFO) << "Client to Codec2 service \"" << name << "\" created";
833 return std::make_shared<Codec2Client>(baseStore, index);
834}
835
836c2_status_t Codec2Client::ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800837 const std::string &key,
Pawin Vongmasa54782cf2019-10-09 02:15:50 -0700838 size_t numberOfAttempts,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800839 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
840 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800841 c2_status_t status = C2_NO_INIT; // no IComponentStores present
842
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700843 // Cache the mapping key -> index of Codec2Client in Cache::List().
Pawin Vongmasa36653902018-11-15 00:10:25 -0800844 static std::mutex key2IndexMutex;
845 static std::map<std::string, size_t> key2Index;
846
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800847 // By default try all stores. However, try the last known client first. If
848 // the last known client fails, retry once. We do this by pushing the last
849 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800850 std::deque<size_t> indices;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700851 for (size_t index = Cache::List().size(); index > 0; ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800852 indices.push_front(--index);
853 }
854
855 bool wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700856 {
857 std::scoped_lock lock{key2IndexMutex};
858 auto it = key2Index.find(key);
859 if (it != key2Index.end()) {
860 indices.push_front(it->second);
861 wasMapped = true;
862 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800863 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800864
865 for (size_t index : indices) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700866 Cache& cache = Cache::List()[index];
Pawin Vongmasa54782cf2019-10-09 02:15:50 -0700867 for (size_t tries = numberOfAttempts; tries > 0; --tries) {
868 std::shared_ptr<Codec2Client> client{cache.getClient()};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800869 status = predicate(client);
870 if (status == C2_OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700871 std::scoped_lock lock{key2IndexMutex};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800872 key2Index[key] = index; // update last known client index
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700873 return C2_OK;
Pawin Vongmasa54782cf2019-10-09 02:15:50 -0700874 } else if (status == C2_TRANSACTION_FAILED) {
875 LOG(WARNING) << "\"" << key << "\" failed for service \""
876 << client->getName()
877 << "\" due to transaction failure. "
878 << "(Service may have crashed.)"
879 << (tries > 1 ? " Retrying..." : "");
880 cache.invalidate();
881 continue;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800882 }
Pawin Vongmasa54782cf2019-10-09 02:15:50 -0700883 if (wasMapped) {
884 LOG(INFO) << "\"" << key << "\" became invalid in service \""
885 << client->getName() << "\". Retrying...";
886 wasMapped = false;
887 }
888 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800889 }
890 }
Pawin Vongmasa54782cf2019-10-09 02:15:50 -0700891 return status; // return the last status from a valid client
Pawin Vongmasa36653902018-11-15 00:10:25 -0800892}
893
894std::shared_ptr<Codec2Client::Component>
895 Codec2Client::CreateComponentByName(
896 const char* componentName,
897 const std::shared_ptr<Listener>& listener,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -0700898 std::shared_ptr<Codec2Client>* owner,
899 size_t numberOfAttempts) {
Pawin Vongmasa54782cf2019-10-09 02:15:50 -0700900 std::string key{"create:"};
901 key.append(componentName);
902 std::shared_ptr<Component> component;
903 c2_status_t status = ForAllServices(
904 key,
905 numberOfAttempts,
906 [owner, &component, componentName, &listener](
907 const std::shared_ptr<Codec2Client> &client)
908 -> c2_status_t {
909 c2_status_t status = client->createComponent(componentName,
910 listener,
911 &component);
912 if (status == C2_OK) {
913 if (owner) {
914 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800915 }
Pawin Vongmasa54782cf2019-10-09 02:15:50 -0700916 } else if (status != C2_NOT_FOUND) {
917 LOG(DEBUG) << "IComponentStore("
918 << client->getServiceName()
919 << ")::createComponent(\"" << componentName
920 << "\") returned status = "
921 << status << ".";
922 }
923 return status;
924 });
925 if (status != C2_OK) {
926 LOG(DEBUG) << "Failed to create component \"" << componentName
927 << "\" from all known services. "
928 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800929 }
Pawin Vongmasa54782cf2019-10-09 02:15:50 -0700930 return component;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800931}
932
933std::shared_ptr<Codec2Client::Interface>
934 Codec2Client::CreateInterfaceByName(
935 const char* interfaceName,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -0700936 std::shared_ptr<Codec2Client>* owner,
937 size_t numberOfAttempts) {
Pawin Vongmasa54782cf2019-10-09 02:15:50 -0700938 std::string key{"create:"};
939 key.append(interfaceName);
940 std::shared_ptr<Interface> interface;
941 c2_status_t status = ForAllServices(
942 key,
943 numberOfAttempts,
944 [owner, &interface, interfaceName](
945 const std::shared_ptr<Codec2Client> &client)
946 -> c2_status_t {
947 c2_status_t status = client->createInterface(interfaceName,
948 &interface);
949 if (status == C2_OK) {
950 if (owner) {
951 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800952 }
Pawin Vongmasa54782cf2019-10-09 02:15:50 -0700953 } else if (status != C2_NOT_FOUND) {
954 LOG(DEBUG) << "IComponentStore("
955 << client->getServiceName()
956 << ")::createInterface(\"" << interfaceName
957 << "\") returned status = "
958 << status << ".";
959 }
960 return status;
961 });
962 if (status != C2_OK) {
963 LOG(DEBUG) << "Failed to create interface \"" << interfaceName
964 << "\" from all known services. "
965 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800966 }
Pawin Vongmasa54782cf2019-10-09 02:15:50 -0700967 return interface;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800968}
969
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700970std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
971 static std::vector<C2Component::Traits> sList{[]() {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800972 std::vector<C2Component::Traits> list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700973 for (Cache& cache : Cache::List()) {
974 std::vector<C2Component::Traits> const& traits = cache.getTraits();
975 list.insert(list.end(), traits.begin(), traits.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800976 }
977 return list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700978 }()};
979 return sList;
980}
Pawin Vongmasa36653902018-11-15 00:10:25 -0800981
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700982std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
983 char const* serviceName) {
Pawin Vongmasa18588322019-05-18 01:52:13 -0700984 int32_t inputSurfaceSetting = ::android::base::GetIntProperty(
985 "debug.stagefright.c2inputsurface", int32_t(0));
986 if (inputSurfaceSetting <= 0) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700987 return nullptr;
988 }
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700989 size_t index = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700990 if (serviceName) {
991 index = getServiceIndex(serviceName);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700992 if (index == GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700993 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
994 << serviceName << "\"";
995 }
996 }
997
998 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700999 if (index != GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001000 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
1001 if (client->createInputSurface(&inputSurface) == C2_OK) {
1002 return inputSurface;
1003 }
1004 }
1005 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
1006 "from all services...";
1007 for (Cache& cache : Cache::List()) {
1008 std::shared_ptr<Codec2Client> client = cache.getClient();
1009 if (client->createInputSurface(&inputSurface) == C2_OK) {
1010 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
1011 "service \"" << client->getServiceName() << "\"";
1012 return inputSurface;
1013 }
1014 }
1015 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
1016 "from all services";
1017 return nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001018}
1019
1020// Codec2Client::Listener
1021
1022Codec2Client::Listener::~Listener() {
1023}
1024
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001025// Codec2Client::Interface
1026Codec2Client::Interface::Interface(const sp<Base>& base)
1027 : Configurable{
1028 [base]() -> sp<IConfigurable> {
1029 Return<sp<IConfigurable>> transResult =
1030 base->getConfigurable();
1031 return transResult.isOk() ?
1032 static_cast<sp<IConfigurable>>(transResult) :
1033 nullptr;
1034 }()
1035 },
1036 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001037}
1038
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001039// Codec2Client::Component
1040Codec2Client::Component::Component(const sp<Base>& base)
1041 : Configurable{
1042 [base]() -> sp<IConfigurable> {
1043 Return<sp<IComponentInterface>> transResult1 =
1044 base->getInterface();
1045 if (!transResult1.isOk()) {
1046 return nullptr;
1047 }
1048 Return<sp<IConfigurable>> transResult2 =
1049 static_cast<sp<IComponentInterface>>(transResult1)->
1050 getConfigurable();
1051 return transResult2.isOk() ?
1052 static_cast<sp<IConfigurable>>(transResult2) :
1053 nullptr;
1054 }()
1055 },
1056 mBase{base},
1057 mBufferPoolSender{nullptr} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001058}
1059
1060Codec2Client::Component::~Component() {
1061}
1062
1063c2_status_t Codec2Client::Component::createBlockPool(
1064 C2Allocator::id_t id,
1065 C2BlockPool::local_id_t* blockPoolId,
1066 std::shared_ptr<Codec2Client::Configurable>* configurable) {
1067 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001068 Return<void> transStatus = mBase->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001069 static_cast<uint32_t>(id),
1070 [&status, blockPoolId, configurable](
1071 Status s,
1072 uint64_t pId,
1073 const sp<IConfigurable>& c) {
1074 status = static_cast<c2_status_t>(s);
1075 configurable->reset();
1076 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001077 LOG(DEBUG) << "createBlockPool -- call failed: "
1078 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001079 return;
1080 }
1081 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001082 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001083 });
1084 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001085 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001086 return C2_TRANSACTION_FAILED;
1087 }
1088 return status;
1089}
1090
1091c2_status_t Codec2Client::Component::destroyBlockPool(
1092 C2BlockPool::local_id_t localId) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001093 Return<Status> transResult = mBase->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001094 static_cast<uint64_t>(localId));
1095 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001096 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001097 return C2_TRANSACTION_FAILED;
1098 }
1099 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1100}
1101
Wonsik Kimab34ed62019-01-31 15:28:46 -08001102void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001103 const std::list<std::unique_ptr<C2Work>> &workItems) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001104 // Output bufferqueue-based blocks' lifetime management
Sungtak Lee08515812019-06-05 11:16:32 -07001105 mOutputBufferQueue.holdBufferQueueBlocks(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001106}
1107
1108c2_status_t Codec2Client::Component::queue(
1109 std::list<std::unique_ptr<C2Work>>* const items) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001110 WorkBundle workBundle;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001111 if (!objcpy(&workBundle, *items, &mBufferPoolSender)) {
1112 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001113 return C2_TRANSACTION_FAILED;
1114 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001115 Return<Status> transStatus = mBase->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001116 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001117 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001118 return C2_TRANSACTION_FAILED;
1119 }
1120 c2_status_t status =
1121 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1122 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001123 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001124 }
1125 return status;
1126}
1127
1128c2_status_t Codec2Client::Component::flush(
1129 C2Component::flush_mode_t mode,
1130 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
1131 (void)mode; // Flush mode isn't supported in HIDL yet.
1132 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001133 Return<void> transStatus = mBase->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001134 [&status, flushedWork](
1135 Status s, const WorkBundle& wb) {
1136 status = static_cast<c2_status_t>(s);
1137 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001138 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001139 return;
1140 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001141 if (!objcpy(flushedWork, wb)) {
1142 status = C2_CORRUPTED;
1143 } else {
1144 status = C2_OK;
1145 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001146 });
1147 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001148 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001149 return C2_TRANSACTION_FAILED;
1150 }
1151
1152 // Indices of flushed work items.
1153 std::vector<uint64_t> flushedIndices;
1154 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
1155 if (work) {
1156 if (work->worklets.empty()
1157 || !work->worklets.back()
1158 || (work->worklets.back()->output.flags &
1159 C2FrameData::FLAG_INCOMPLETE) == 0) {
1160 // input is complete
1161 flushedIndices.emplace_back(
1162 work->input.ordinal.frameIndex.peeku());
1163 }
1164 }
1165 }
1166
Pawin Vongmasa36653902018-11-15 00:10:25 -08001167 // Output bufferqueue-based blocks' lifetime management
Sungtak Lee08515812019-06-05 11:16:32 -07001168 mOutputBufferQueue.holdBufferQueueBlocks(*flushedWork);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001169
1170 return status;
1171}
1172
1173c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001174 Return<Status> transStatus = mBase->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001175 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1176 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001177 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001178 return C2_TRANSACTION_FAILED;
1179 }
1180 c2_status_t status =
1181 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1182 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001183 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001184 }
1185 return status;
1186}
1187
1188c2_status_t Codec2Client::Component::start() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001189 Return<Status> transStatus = mBase->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001190 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001191 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001192 return C2_TRANSACTION_FAILED;
1193 }
1194 c2_status_t status =
1195 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1196 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001197 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001198 }
1199 return status;
1200}
1201
1202c2_status_t Codec2Client::Component::stop() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001203 Return<Status> transStatus = mBase->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001204 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001205 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001206 return C2_TRANSACTION_FAILED;
1207 }
1208 c2_status_t status =
1209 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1210 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001211 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001212 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001213 return status;
1214}
1215
1216c2_status_t Codec2Client::Component::reset() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001217 Return<Status> transStatus = mBase->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001218 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001219 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001220 return C2_TRANSACTION_FAILED;
1221 }
1222 c2_status_t status =
1223 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1224 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001225 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001226 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001227 return status;
1228}
1229
1230c2_status_t Codec2Client::Component::release() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001231 Return<Status> transStatus = mBase->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001232 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001233 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001234 return C2_TRANSACTION_FAILED;
1235 }
1236 c2_status_t status =
1237 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1238 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001239 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001240 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001241 return status;
1242}
1243
1244c2_status_t Codec2Client::Component::setOutputSurface(
1245 C2BlockPool::local_id_t blockPoolId,
1246 const sp<IGraphicBufferProducer>& surface,
1247 uint32_t generation) {
Sungtak Lee08515812019-06-05 11:16:32 -07001248 uint64_t bqId = 0;
1249 sp<IGraphicBufferProducer> nullIgbp;
1250 sp<HGraphicBufferProducer2> nullHgbp;
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08001251
Sungtak Lee08515812019-06-05 11:16:32 -07001252 sp<HGraphicBufferProducer2> igbp = surface ?
1253 surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
1254 if (surface && !igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001255 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001256 }
1257
Sungtak Lee08515812019-06-05 11:16:32 -07001258 if (!surface) {
1259 mOutputBufferQueue.configure(nullIgbp, generation, 0);
1260 } else if (surface->getUniqueId(&bqId) != OK) {
1261 LOG(ERROR) << "setOutputSurface -- "
1262 "cannot obtain bufferqueue id.";
1263 bqId = 0;
1264 mOutputBufferQueue.configure(nullIgbp, generation, 0);
1265 } else {
1266 mOutputBufferQueue.configure(surface, generation, bqId);
1267 }
1268 ALOGD("generation remote change %u", generation);
1269
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001270 Return<Status> transStatus = mBase->setOutputSurface(
Sungtak Lee08515812019-06-05 11:16:32 -07001271 static_cast<uint64_t>(blockPoolId),
1272 bqId == 0 ? nullHgbp : igbp);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001273 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001274 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001275 return C2_TRANSACTION_FAILED;
1276 }
1277 c2_status_t status =
1278 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1279 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001280 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001281 }
1282 return status;
1283}
1284
1285status_t Codec2Client::Component::queueToOutputSurface(
1286 const C2ConstGraphicBlock& block,
1287 const QueueBufferInput& input,
1288 QueueBufferOutput* output) {
Sungtak Lee08515812019-06-05 11:16:32 -07001289 return mOutputBufferQueue.outputBuffer(block, input, output);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001290}
1291
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001292c2_status_t Codec2Client::Component::connectToInputSurface(
1293 const std::shared_ptr<InputSurface>& inputSurface,
1294 std::shared_ptr<InputSurfaceConnection>* connection) {
1295 c2_status_t status;
1296 Return<void> transStatus = mBase->connectToInputSurface(
1297 inputSurface->mBase,
1298 [&status, connection](
1299 Status s, const sp<IInputSurfaceConnection>& c) {
1300 status = static_cast<c2_status_t>(s);
1301 if (status != C2_OK) {
1302 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1303 << status << ".";
1304 return;
1305 }
1306 *connection = std::make_shared<InputSurfaceConnection>(c);
1307 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001308 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001309 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001310 return C2_TRANSACTION_FAILED;
1311 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001312 return status;
1313}
1314
1315c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001316 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001317 const sp<HGraphicBufferSource>& source,
1318 std::shared_ptr<InputSurfaceConnection>* connection) {
1319 c2_status_t status;
1320 Return<void> transStatus = mBase->connectToOmxInputSurface(
1321 producer, source,
1322 [&status, connection](
1323 Status s, const sp<IInputSurfaceConnection>& c) {
1324 status = static_cast<c2_status_t>(s);
1325 if (status != C2_OK) {
1326 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1327 << status << ".";
1328 return;
1329 }
1330 *connection = std::make_shared<InputSurfaceConnection>(c);
1331 });
1332 if (!transStatus.isOk()) {
1333 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1334 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001335 }
1336 return status;
1337}
1338
1339c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001340 Return<Status> transStatus = mBase->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001341 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001342 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001343 return C2_TRANSACTION_FAILED;
1344 }
1345 c2_status_t status =
1346 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1347 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001348 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1349 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001350 }
1351 return status;
1352}
1353
1354c2_status_t Codec2Client::Component::setDeathListener(
1355 const std::shared_ptr<Component>& component,
1356 const std::shared_ptr<Listener>& listener) {
1357
1358 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1359 std::weak_ptr<Component> component;
1360 std::weak_ptr<Listener> base;
1361
1362 virtual void serviceDied(
1363 uint64_t /* cookie */,
1364 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1365 ) override {
1366 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1367 listener->onDeath(component);
1368 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001369 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001370 }
1371 }
1372 };
1373
1374 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1375 deathRecipient->base = listener;
1376 deathRecipient->component = component;
1377
1378 component->mDeathRecipient = deathRecipient;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001379 Return<bool> transResult = component->mBase->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001380 component->mDeathRecipient, 0);
1381 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001382 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001383 return C2_TRANSACTION_FAILED;
1384 }
1385 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001386 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001387 return C2_CORRUPTED;
1388 }
1389 return C2_OK;
1390}
1391
1392// Codec2Client::InputSurface
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001393Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base)
1394 : Configurable{
1395 [base]() -> sp<IConfigurable> {
1396 Return<sp<IConfigurable>> transResult =
1397 base->getConfigurable();
1398 return transResult.isOk() ?
1399 static_cast<sp<IConfigurable>>(transResult) :
1400 nullptr;
1401 }()
1402 },
1403 mBase{base},
1404 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001405 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
1406 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001407 base->getGraphicBufferProducer();
1408 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001409 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001410 nullptr;
1411 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001412}
1413
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001414sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08001415 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1416 return mGraphicBufferProducer;
1417}
1418
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001419sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001420 return mBase;
1421}
1422
1423// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08001424Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001425 const sp<IInputSurfaceConnection>& base)
1426 : Configurable{
1427 [base]() -> sp<IConfigurable> {
1428 Return<sp<IConfigurable>> transResult =
1429 base->getConfigurable();
1430 return transResult.isOk() ?
1431 static_cast<sp<IConfigurable>>(transResult) :
1432 nullptr;
1433 }()
1434 },
1435 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001436}
1437
1438c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001439 Return<Status> transResult = mBase->disconnect();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001440 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1441}
1442
1443} // namespace android
1444