blob: 5ed54f1a24827aae0a451e2bf31dcfdbba8415af [file] [log] [blame]
Pawin Vongmasa36653902018-11-15 00:10:25 -08001/*
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002 * Copyright 2018 The Android Open Source Project
Pawin Vongmasa36653902018-11-15 00:10:25 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "Codec2Client"
Pawin Vongmasa1c75a232019-01-09 04:41:52 -080019#include <android-base/logging.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080020
21#include <codec2/hidl/client.h>
22
23#include <deque>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070024#include <iterator>
Pawin Vongmasa36653902018-11-15 00:10:25 -080025#include <limits>
26#include <map>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070027#include <mutex>
28#include <sstream>
29#include <thread>
Pawin Vongmasa36653902018-11-15 00:10:25 -080030#include <type_traits>
31#include <vector>
32
33#include <android-base/properties.h>
34#include <bufferpool/ClientManager.h>
35#include <cutils/native_handle.h>
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080036#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
37#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080038#include <hidl/HidlSupport.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080039
Sungtak Leed3318082018-09-07 15:52:43 -070040#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
Pawin Vongmasad0f0e142018-11-15 03:36:28 -080041#include <android/hardware/media/c2/1.0/IComponent.h>
42#include <android/hardware/media/c2/1.0/IComponentInterface.h>
43#include <android/hardware/media/c2/1.0/IComponentListener.h>
44#include <android/hardware/media/c2/1.0/IComponentStore.h>
45#include <android/hardware/media/c2/1.0/IConfigurable.h>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070046#include <android/hidl/manager/1.2/IServiceManager.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080047
48#include <C2Debug.h>
49#include <C2BufferPriv.h>
50#include <C2PlatformSupport.h>
51
52namespace android {
53
54using ::android::hardware::hidl_vec;
55using ::android::hardware::hidl_string;
56using ::android::hardware::Return;
57using ::android::hardware::Void;
Pawin Vongmasa36653902018-11-15 00:10:25 -080058
Pawin Vongmasad0f0e142018-11-15 03:36:28 -080059using namespace ::android::hardware::media::c2::V1_0;
60using namespace ::android::hardware::media::c2::V1_0::utils;
Sungtak Leed3318082018-09-07 15:52:43 -070061using namespace ::android::hardware::media::bufferpool::V2_0;
62using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
Pawin Vongmasa36653902018-11-15 00:10:25 -080063
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080064using HGraphicBufferProducer1 = ::android::hardware::graphics::bufferqueue::
65 V1_0::IGraphicBufferProducer;
66using HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
67 V2_0::IGraphicBufferProducer;
68using B2HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
69 V2_0::utils::B2HGraphicBufferProducer;
70using H2BGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
71 V2_0::utils::H2BGraphicBufferProducer;
72
Pawin Vongmasa36653902018-11-15 00:10:25 -080073namespace /* unnamed */ {
74
75// c2_status_t value that corresponds to hwbinder transaction failure.
76constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
77
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070078// Searches for a name in GetServiceNames() and returns the index found. If the
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070079// name is not found, the returned index will be equal to
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070080// GetServiceNames().size().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070081size_t getServiceIndex(char const* name) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070082 std::vector<std::string> const& names = Codec2Client::GetServiceNames();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070083 size_t i = 0;
84 for (; i < names.size(); ++i) {
85 if (name == names[i]) {
86 break;
87 }
Pawin Vongmasa36653902018-11-15 00:10:25 -080088 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070089 return i;
Pawin Vongmasa36653902018-11-15 00:10:25 -080090}
91
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070092} // unnamed namespace
93
94// This class caches a Codec2Client object and its component traits. The client
95// will be created the first time it is needed, and it can be refreshed if the
96// service dies (by calling invalidate()). The first time listComponents() is
97// called from the client, the result will be cached.
98class Codec2Client::Cache {
99 // Cached client
100 std::shared_ptr<Codec2Client> mClient;
101 mutable std::mutex mClientMutex;
102
103 // Cached component traits
104 std::vector<C2Component::Traits> mTraits;
105 std::once_flag mTraitsInitializationFlag;
106
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700107 // The index of the service. This is based on GetServiceNames().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700108 size_t mIndex;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700109 // Called by s() exactly once to initialize the cache. The index must be a
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700110 // valid index into the vector returned by GetServiceNames(). Calling
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700111 // init(index) will associate the cache to the service with name
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700112 // GetServiceNames()[index].
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700113 void init(size_t index) {
114 mIndex = index;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700115 }
116
117public:
118 Cache() = default;
119
120 // Initializes mClient if needed, then returns mClient.
121 // If the service is unavailable but listed in the manifest, this function
122 // will block indefinitely.
123 std::shared_ptr<Codec2Client> getClient() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700124 std::scoped_lock lock{mClientMutex};
125 if (!mClient) {
126 mClient = Codec2Client::_CreateFromIndex(mIndex);
127 }
128 return mClient;
129 }
130
131 // Causes a subsequent call to getClient() to create a new client. This
132 // function should be called after the service dies.
133 //
134 // Note: This function is called only by ForAllServices().
135 void invalidate() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700136 std::scoped_lock lock{mClientMutex};
137 mClient = nullptr;
138 }
139
140 // Returns a list of traits for components supported by the service. This
141 // list is cached.
142 std::vector<C2Component::Traits> const& getTraits() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700143 std::call_once(mTraitsInitializationFlag, [this]() {
144 bool success{false};
145 // Spin until _listComponents() is successful.
146 while (true) {
147 std::shared_ptr<Codec2Client> client = getClient();
148 mTraits = client->_listComponents(&success);
149 if (success) {
150 break;
151 }
152 using namespace std::chrono_literals;
153 static constexpr auto kServiceRetryPeriod = 5s;
154 LOG(INFO) << "Failed to retrieve component traits from service "
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700155 "\"" << GetServiceNames()[mIndex] << "\". "
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700156 "Retrying...";
157 std::this_thread::sleep_for(kServiceRetryPeriod);
158 }
159 });
160 return mTraits;
161 }
162
163 // List() returns the list of all caches.
164 static std::vector<Cache>& List() {
165 static std::vector<Cache> sCaches{[]() {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700166 size_t numServices = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700167 std::vector<Cache> caches(numServices);
168 for (size_t i = 0; i < numServices; ++i) {
169 caches[i].init(i);
170 }
171 return caches;
172 }()};
173 return sCaches;
174 }
175};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800176
177// Codec2ConfigurableClient
178
179const C2String& Codec2ConfigurableClient::getName() const {
180 return mName;
181}
182
Pawin Vongmasa36653902018-11-15 00:10:25 -0800183Codec2ConfigurableClient::Codec2ConfigurableClient(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800184 const sp<IConfigurable>& base)
185 : mBase{base},
186 mName{[base]() -> C2String {
187 C2String outName;
188 Return<void> transStatus = base->getName(
189 [&outName](const hidl_string& name) {
190 outName = name.c_str();
191 });
192 return transStatus.isOk() ? outName : "";
193 }()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800194}
195
196c2_status_t Codec2ConfigurableClient::query(
197 const std::vector<C2Param*> &stackParams,
198 const std::vector<C2Param::Index> &heapParamIndices,
199 c2_blocking_t mayBlock,
200 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
201 hidl_vec<ParamIndex> indices(
202 stackParams.size() + heapParamIndices.size());
203 size_t numIndices = 0;
204 for (C2Param* const& stackParam : stackParams) {
205 if (!stackParam) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800206 LOG(WARNING) << "query -- null stack param encountered.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800207 continue;
208 }
209 indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
210 }
211 size_t numStackIndices = numIndices;
212 for (const C2Param::Index& index : heapParamIndices) {
213 indices[numIndices++] =
214 static_cast<ParamIndex>(static_cast<uint32_t>(index));
215 }
216 indices.resize(numIndices);
217 if (heapParams) {
218 heapParams->reserve(heapParams->size() + numIndices);
219 }
220 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800221 Return<void> transStatus = mBase->query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800222 indices,
223 mayBlock == C2_MAY_BLOCK,
224 [&status, &numStackIndices, &stackParams, heapParams](
225 Status s, const Params& p) {
226 status = static_cast<c2_status_t>(s);
227 if (status != C2_OK && status != C2_BAD_INDEX) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800228 LOG(DEBUG) << "query -- call failed: "
229 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800230 return;
231 }
232 std::vector<C2Param*> paramPointers;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800233 if (!parseParamsBlob(&paramPointers, p)) {
234 LOG(ERROR) << "query -- error while parsing params.";
235 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800236 return;
237 }
238 size_t i = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800239 for (auto it = paramPointers.begin();
240 it != paramPointers.end(); ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800241 C2Param* paramPointer = *it;
242 if (numStackIndices > 0) {
243 --numStackIndices;
244 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800245 LOG(WARNING) << "query -- null stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800246 ++it;
247 continue;
248 }
249 for (; i < stackParams.size() && !stackParams[i]; ) {
250 ++i;
251 }
252 if (i >= stackParams.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800253 LOG(ERROR) << "query -- unexpected error.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800254 status = C2_CORRUPTED;
255 return;
256 }
257 if (stackParams[i]->index() != paramPointer->index()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800258 LOG(WARNING) << "query -- param skipped: "
259 "index = "
260 << stackParams[i]->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800261 stackParams[i++]->invalidate();
262 continue;
263 }
264 if (!stackParams[i++]->updateFrom(*paramPointer)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800265 LOG(WARNING) << "query -- param update failed: "
266 "index = "
267 << paramPointer->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800268 }
269 } else {
270 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800271 LOG(WARNING) << "query -- null heap param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800272 ++it;
273 continue;
274 }
275 if (!heapParams) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800276 LOG(WARNING) << "query -- "
277 "unexpected extra stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800278 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800279 heapParams->emplace_back(
280 C2Param::Copy(*paramPointer));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800281 }
282 }
283 ++it;
284 }
285 });
286 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800287 LOG(ERROR) << "query -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800288 return C2_TRANSACTION_FAILED;
289 }
290 return status;
291}
292
293c2_status_t Codec2ConfigurableClient::config(
294 const std::vector<C2Param*> &params,
295 c2_blocking_t mayBlock,
296 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
297 Params hidlParams;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800298 if (!createParamsBlob(&hidlParams, params)) {
299 LOG(ERROR) << "config -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800300 return C2_TRANSACTION_FAILED;
301 }
302 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800303 Return<void> transStatus = mBase->config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800304 hidlParams,
305 mayBlock == C2_MAY_BLOCK,
306 [&status, &params, failures](
307 Status s,
308 const hidl_vec<SettingResult> f,
309 const Params& o) {
310 status = static_cast<c2_status_t>(s);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800311 if (status != C2_OK && status != C2_BAD_INDEX) {
312 LOG(DEBUG) << "config -- call failed: "
313 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800314 }
315 size_t i = failures->size();
316 failures->resize(i + f.size());
317 for (const SettingResult& sf : f) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800318 if (!objcpy(&(*failures)[i++], sf)) {
319 LOG(ERROR) << "config -- "
320 << "invalid SettingResult returned.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800321 return;
322 }
323 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800324 if (!updateParamsFromBlob(params, o)) {
325 LOG(ERROR) << "config -- "
326 << "failed to parse returned params.";
327 status = C2_CORRUPTED;
328 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800329 });
330 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800331 LOG(ERROR) << "config -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800332 return C2_TRANSACTION_FAILED;
333 }
334 return status;
335}
336
337c2_status_t Codec2ConfigurableClient::querySupportedParams(
338 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
339 // TODO: Cache and query properly!
340 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800341 Return<void> transStatus = mBase->querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800342 std::numeric_limits<uint32_t>::min(),
343 std::numeric_limits<uint32_t>::max(),
344 [&status, params](
345 Status s,
346 const hidl_vec<ParamDescriptor>& p) {
347 status = static_cast<c2_status_t>(s);
348 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800349 LOG(DEBUG) << "querySupportedParams -- call failed: "
350 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800351 return;
352 }
353 size_t i = params->size();
354 params->resize(i + p.size());
355 for (const ParamDescriptor& sp : p) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800356 if (!objcpy(&(*params)[i++], sp)) {
357 LOG(ERROR) << "querySupportedParams -- "
358 << "invalid returned ParamDescriptor.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800359 return;
360 }
361 }
362 });
363 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800364 LOG(ERROR) << "querySupportedParams -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800365 return C2_TRANSACTION_FAILED;
366 }
367 return status;
368}
369
370c2_status_t Codec2ConfigurableClient::querySupportedValues(
371 std::vector<C2FieldSupportedValuesQuery>& fields,
372 c2_blocking_t mayBlock) const {
373 hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
374 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800375 if (!objcpy(&inFields[i], fields[i])) {
376 LOG(ERROR) << "querySupportedValues -- bad input";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800377 return C2_TRANSACTION_FAILED;
378 }
379 }
380
381 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800382 Return<void> transStatus = mBase->querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800383 inFields,
384 mayBlock == C2_MAY_BLOCK,
385 [&status, &inFields, &fields](
386 Status s,
387 const hidl_vec<FieldSupportedValuesQueryResult>& r) {
388 status = static_cast<c2_status_t>(s);
389 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800390 LOG(DEBUG) << "querySupportedValues -- call failed: "
391 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800392 return;
393 }
394 if (r.size() != fields.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800395 LOG(ERROR) << "querySupportedValues -- "
396 "input and output lists "
397 "have different sizes.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800398 status = C2_CORRUPTED;
399 return;
400 }
401 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800402 if (!objcpy(&fields[i], inFields[i], r[i])) {
403 LOG(ERROR) << "querySupportedValues -- "
404 "invalid returned value.";
405 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800406 return;
407 }
408 }
409 });
410 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800411 LOG(ERROR) << "querySupportedValues -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800412 return C2_TRANSACTION_FAILED;
413 }
414 return status;
415}
416
417// Codec2Client::Component::HidlListener
418struct Codec2Client::Component::HidlListener : public IComponentListener {
419 std::weak_ptr<Component> component;
420 std::weak_ptr<Listener> base;
421
422 virtual Return<void> onWorkDone(const WorkBundle& workBundle) override {
423 std::list<std::unique_ptr<C2Work>> workItems;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800424 if (!objcpy(&workItems, workBundle)) {
425 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800426 return Void();
427 }
428 // release input buffers potentially held by the component from queue
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800429 std::shared_ptr<Codec2Client::Component> strongComponent =
430 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800431 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800432 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800433 }
434 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800435 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800436 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800437 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800438 }
439 return Void();
440 }
441
442 virtual Return<void> onTripped(
443 const hidl_vec<SettingResult>& settingResults) override {
444 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
445 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800446 for (size_t i = 0; i < settingResults.size(); ++i) {
447 std::unique_ptr<C2SettingResult> c2SettingResult;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800448 if (!objcpy(&c2SettingResult, settingResults[i])) {
449 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800450 return Void();
451 }
452 c2SettingResults[i] = std::move(c2SettingResult);
453 }
454 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
455 listener->onTripped(component, c2SettingResults);
456 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800457 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800458 }
459 return Void();
460 }
461
462 virtual Return<void> onError(Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800463 LOG(DEBUG) << "onError --"
464 << " status = " << s
465 << ", errorCode = " << errorCode
466 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800467 if (std::shared_ptr<Listener> listener = base.lock()) {
468 listener->onError(component, s == Status::OK ?
469 errorCode : static_cast<c2_status_t>(s));
470 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800471 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800472 }
473 return Void();
474 }
475
476 virtual Return<void> onFramesRendered(
477 const hidl_vec<RenderedFrame>& renderedFrames) override {
478 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800479 if (!listener) {
480 LOG(DEBUG) << "onFramesRendered -- listener died.";
481 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800482 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800483 for (const RenderedFrame& renderedFrame : renderedFrames) {
484 listener->onFrameRendered(
485 renderedFrame.bufferQueueId,
486 renderedFrame.slotId,
487 renderedFrame.timestampNs);
488 }
489 return Void();
490 }
491
492 virtual Return<void> onInputBuffersReleased(
493 const hidl_vec<InputBuffer>& inputBuffers) override {
494 std::shared_ptr<Listener> listener = base.lock();
495 if (!listener) {
496 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
497 return Void();
498 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800499 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800500 LOG(VERBOSE) << "onInputBuffersReleased --"
501 " received death notification of"
502 " input buffer:"
503 " frameIndex = " << inputBuffer.frameIndex
504 << ", bufferIndex = " << inputBuffer.arrayIndex
505 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -0800506 listener->onInputBufferDone(
507 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800508 }
509 return Void();
510 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800511
Pawin Vongmasa36653902018-11-15 00:10:25 -0800512};
513
514// Codec2Client
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800515Codec2Client::Codec2Client(const sp<IComponentStore>& base,
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700516 size_t serviceIndex)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800517 : Configurable{
518 [base]() -> sp<IConfigurable> {
519 Return<sp<IConfigurable>> transResult =
520 base->getConfigurable();
521 return transResult.isOk() ?
522 static_cast<sp<IConfigurable>>(transResult) :
523 nullptr;
524 }()
525 },
526 mBase{base},
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700527 mServiceIndex{serviceIndex} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800528 Return<sp<IClientManager>> transResult = base->getPoolClientManager();
529 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800530 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800531 } else {
532 mHostPoolManager = static_cast<sp<IClientManager>>(transResult);
533 }
534}
535
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700536sp<Codec2Client::Base> const& Codec2Client::getBase() const {
537 return mBase;
538}
539
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700540std::string const& Codec2Client::getServiceName() const {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700541 return GetServiceNames()[mServiceIndex];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700542}
543
Pawin Vongmasa36653902018-11-15 00:10:25 -0800544c2_status_t Codec2Client::createComponent(
545 const C2String& name,
546 const std::shared_ptr<Codec2Client::Listener>& listener,
547 std::shared_ptr<Codec2Client::Component>* const component) {
548
Pawin Vongmasa36653902018-11-15 00:10:25 -0800549 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800550 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800551 hidlListener->base = listener;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800552 Return<void> transStatus = mBase->createComponent(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800553 name,
554 hidlListener,
555 ClientManager::getInstance(),
556 [&status, component, hidlListener](
557 Status s,
558 const sp<IComponent>& c) {
559 status = static_cast<c2_status_t>(s);
560 if (status != C2_OK) {
561 return;
562 }
563 *component = std::make_shared<Codec2Client::Component>(c);
564 hidlListener->component = *component;
565 });
566 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800567 LOG(ERROR) << "createComponent(" << name.c_str()
568 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800569 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800570 } else if (status != C2_OK) {
571 LOG(ERROR) << "createComponent(" << name.c_str()
572 << ") -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800573 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800574 } else if (!*component) {
575 LOG(ERROR) << "createComponent(" << name.c_str()
576 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800577 return C2_CORRUPTED;
578 }
579
580 status = (*component)->setDeathListener(*component, listener);
581 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800582 LOG(ERROR) << "createComponent(" << name.c_str()
583 << ") -- failed to set up death listener: "
584 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800585 }
586
587 (*component)->mBufferPoolSender.setReceiver(mHostPoolManager);
588 return status;
589}
590
591c2_status_t Codec2Client::createInterface(
592 const C2String& name,
593 std::shared_ptr<Codec2Client::Interface>* const interface) {
594 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800595 Return<void> transStatus = mBase->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800596 name,
597 [&status, interface](
598 Status s,
599 const sp<IComponentInterface>& i) {
600 status = static_cast<c2_status_t>(s);
601 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800602 return;
603 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800604 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800605 });
606 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800607 LOG(ERROR) << "createInterface(" << name.c_str()
608 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800609 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800610 } else if (status != C2_OK) {
611 LOG(ERROR) << "createComponent(" << name.c_str()
612 << ") -- call failed: " << status << ".";
613 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800614 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800615
Pawin Vongmasa36653902018-11-15 00:10:25 -0800616 return status;
617}
618
619c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800620 std::shared_ptr<InputSurface>* const inputSurface) {
621 c2_status_t status;
622 Return<void> transStatus = mBase->createInputSurface(
623 [&status, inputSurface](
624 Status s,
625 const sp<IInputSurface>& i) {
626 status = static_cast<c2_status_t>(s);
627 if (status != C2_OK) {
628 return;
629 }
630 *inputSurface = std::make_shared<InputSurface>(i);
631 });
632 if (!transStatus.isOk()) {
633 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800634 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800635 } else if (status != C2_OK) {
636 LOG(DEBUG) << "createInputSurface -- call failed: "
637 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800638 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800639 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800640}
641
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700642std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
643 return Cache::List()[mServiceIndex].getTraits();
644}
645
646std::vector<C2Component::Traits> Codec2Client::_listComponents(
647 bool* success) const {
648 std::vector<C2Component::Traits> traits;
649 std::string const& serviceName = getServiceName();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800650 Return<void> transStatus = mBase->listComponents(
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700651 [&traits, &serviceName](Status s,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800652 const hidl_vec<IComponentStore::ComponentTraits>& t) {
653 if (s != Status::OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700654 LOG(DEBUG) << "_listComponents -- call failed: "
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800655 << static_cast<c2_status_t>(s) << ".";
656 return;
657 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700658 traits.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800659 for (size_t i = 0; i < t.size(); ++i) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700660 if (!objcpy(&traits[i], t[i])) {
661 LOG(ERROR) << "_listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800662 return;
663 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700664 traits[i].owner = serviceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800665 }
666 });
667 if (!transStatus.isOk()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700668 LOG(ERROR) << "_listComponents -- transaction failed.";
669 *success = false;
670 } else {
671 *success = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800672 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700673 return traits;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800674}
675
676c2_status_t Codec2Client::copyBuffer(
677 const std::shared_ptr<C2Buffer>& src,
678 const std::shared_ptr<C2Buffer>& dst) {
679 // TODO: Implement?
680 (void)src;
681 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800682 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800683 return C2_OMITTED;
684}
685
686std::shared_ptr<C2ParamReflector>
687 Codec2Client::getParamReflector() {
688 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
689 // should reflect the HAL API.
690 struct SimpleParamReflector : public C2ParamReflector {
691 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
692 hidl_vec<ParamIndex> indices(1);
693 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
694 std::unique_ptr<C2StructDescriptor> descriptor;
695 Return<void> transStatus = mBase->getStructDescriptors(
696 indices,
697 [&descriptor](
698 Status s,
699 const hidl_vec<StructDescriptor>& sd) {
700 c2_status_t status = static_cast<c2_status_t>(s);
701 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800702 LOG(DEBUG) << "SimpleParamReflector -- "
703 "getStructDescriptors() failed: "
704 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800705 descriptor.reset();
706 return;
707 }
708 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800709 LOG(DEBUG) << "SimpleParamReflector -- "
710 "getStructDescriptors() "
711 "returned vector of size "
712 << sd.size() << ". "
713 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800714 descriptor.reset();
715 return;
716 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800717 if (!objcpy(&descriptor, sd[0])) {
718 LOG(DEBUG) << "SimpleParamReflector -- "
719 "getStructDescriptors() returned "
720 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800721 descriptor.reset();
722 return;
723 }
724 });
725 return descriptor;
726 }
727
728 SimpleParamReflector(sp<Base> base)
729 : mBase(base) { }
730
731 sp<Base> mBase;
732 };
733
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800734 return std::make_shared<SimpleParamReflector>(mBase);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800735};
736
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700737std::vector<std::string> const& Codec2Client::GetServiceNames() {
738 static std::vector<std::string> sServiceNames{[]() {
739 using ::android::hardware::media::c2::V1_0::IComponentStore;
740 using ::android::hidl::manager::V1_2::IServiceManager;
741
742 while (true) {
743 sp<IServiceManager> serviceManager = IServiceManager::getService();
744 CHECK(serviceManager) << "Hardware service manager is not running.";
745
746 // There are three categories of services based on names.
747 std::vector<std::string> defaultNames; // Prefixed with "default"
748 std::vector<std::string> vendorNames; // Prefixed with "vendor"
749 std::vector<std::string> otherNames; // Others
750 Return<void> transResult;
751 transResult = serviceManager->listManifestByInterface(
752 IComponentStore::descriptor,
753 [&defaultNames, &vendorNames, &otherNames](
754 hidl_vec<hidl_string> const& instanceNames) {
755 for (hidl_string const& instanceName : instanceNames) {
756 char const* name = instanceName.c_str();
757 if (strncmp(name, "default", 7) == 0) {
758 defaultNames.emplace_back(name);
759 } else if (strncmp(name, "vendor", 6) == 0) {
760 vendorNames.emplace_back(name);
761 } else {
762 otherNames.emplace_back(name);
763 }
764 }
765 });
766 if (transResult.isOk()) {
767 // Sort service names in each category.
768 std::sort(defaultNames.begin(), defaultNames.end());
769 std::sort(vendorNames.begin(), vendorNames.end());
770 std::sort(otherNames.begin(), otherNames.end());
771
772 // Concatenate the three lists in this order: default, vendor,
773 // other.
774 std::vector<std::string>& names = defaultNames;
775 names.reserve(names.size() + vendorNames.size() + otherNames.size());
776 names.insert(names.end(),
777 std::make_move_iterator(vendorNames.begin()),
778 std::make_move_iterator(vendorNames.end()));
779 names.insert(names.end(),
780 std::make_move_iterator(otherNames.begin()),
781 std::make_move_iterator(otherNames.end()));
782
783 // Summarize to logcat.
784 if (names.empty()) {
785 LOG(INFO) << "No Codec2 services declared in the manifest.";
786 } else {
787 std::stringstream stringOutput;
788 stringOutput << "Available Codec2 services:";
789 for (std::string const& name : names) {
790 stringOutput << " \"" << name << "\"";
791 }
792 LOG(INFO) << stringOutput.str();
793 }
794
795 return names;
796 }
797 LOG(ERROR) << "Could not retrieve the list of service instances of "
798 << IComponentStore::descriptor
799 << ". Retrying...";
800 }
801 }()};
802 return sServiceNames;
803}
804
Pawin Vongmasa36653902018-11-15 00:10:25 -0800805std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700806 const char* name) {
807 size_t index = getServiceIndex(name);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700808 return index == GetServiceNames().size() ?
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700809 nullptr : _CreateFromIndex(index);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800810}
811
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700812std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
813 CreateFromAllServices() {
814 std::vector<std::shared_ptr<Codec2Client>> clients(
815 GetServiceNames().size());
816 for (size_t i = GetServiceNames().size(); i > 0; ) {
817 --i;
818 clients[i] = _CreateFromIndex(i);
819 }
820 return clients;
821}
822
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700823std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700824 std::string const& name = GetServiceNames()[index];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700825 LOG(INFO) << "Creating a Codec2 client to service \"" << name << "\"";
826 sp<Base> baseStore = Base::getService(name);
827 CHECK(baseStore) << "Codec2 service \"" << name << "\""
828 " inaccessible for unknown reasons.";
829 LOG(INFO) << "Client to Codec2 service \"" << name << "\" created";
830 return std::make_shared<Codec2Client>(baseStore, index);
831}
832
833c2_status_t Codec2Client::ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800834 const std::string &key,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800835 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
836 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800837 c2_status_t status = C2_NO_INIT; // no IComponentStores present
838
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700839 // Cache the mapping key -> index of Codec2Client in Cache::List().
Pawin Vongmasa36653902018-11-15 00:10:25 -0800840 static std::mutex key2IndexMutex;
841 static std::map<std::string, size_t> key2Index;
842
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800843 // By default try all stores. However, try the last known client first. If
844 // the last known client fails, retry once. We do this by pushing the last
845 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800846 std::deque<size_t> indices;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700847 for (size_t index = Cache::List().size(); index > 0; ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800848 indices.push_front(--index);
849 }
850
851 bool wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700852 {
853 std::scoped_lock lock{key2IndexMutex};
854 auto it = key2Index.find(key);
855 if (it != key2Index.end()) {
856 indices.push_front(it->second);
857 wasMapped = true;
858 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800859 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800860
861 for (size_t index : indices) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700862 Cache& cache = Cache::List()[index];
863 std::shared_ptr<Codec2Client> client{cache.getClient()};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800864 if (client) {
865 status = predicate(client);
866 if (status == C2_OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700867 std::scoped_lock lock{key2IndexMutex};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800868 key2Index[key] = index; // update last known client index
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700869 return C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800870 }
871 }
872 if (wasMapped) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800873 LOG(INFO) << "Could not find \"" << key << "\""
874 " in the last instance. Retrying...";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800875 wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700876 cache.invalidate();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800877 }
878 }
879 return status; // return the last status from a valid client
880}
881
882std::shared_ptr<Codec2Client::Component>
883 Codec2Client::CreateComponentByName(
884 const char* componentName,
885 const std::shared_ptr<Listener>& listener,
886 std::shared_ptr<Codec2Client>* owner) {
887 std::shared_ptr<Component> component;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700888 c2_status_t status = ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800889 componentName,
890 [owner, &component, componentName, &listener](
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800891 const std::shared_ptr<Codec2Client> &client)
892 -> c2_status_t {
893 c2_status_t status = client->createComponent(componentName,
894 listener,
895 &component);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800896 if (status == C2_OK) {
897 if (owner) {
898 *owner = client;
899 }
900 } else if (status != C2_NOT_FOUND) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800901 LOG(DEBUG) << "IComponentStore("
902 << client->getServiceName()
903 << ")::createComponent(\"" << componentName
904 << "\") returned status = "
905 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800906 }
907 return status;
908 });
909 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800910 LOG(DEBUG) << "Could not create component \"" << componentName << "\". "
911 "Status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800912 }
913 return component;
914}
915
916std::shared_ptr<Codec2Client::Interface>
917 Codec2Client::CreateInterfaceByName(
918 const char* interfaceName,
919 std::shared_ptr<Codec2Client>* owner) {
920 std::shared_ptr<Interface> interface;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700921 c2_status_t status = ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800922 interfaceName,
923 [owner, &interface, interfaceName](
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800924 const std::shared_ptr<Codec2Client> &client)
925 -> c2_status_t {
926 c2_status_t status = client->createInterface(interfaceName,
927 &interface);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800928 if (status == C2_OK) {
929 if (owner) {
930 *owner = client;
931 }
932 } else if (status != C2_NOT_FOUND) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800933 LOG(DEBUG) << "IComponentStore("
934 << client->getServiceName()
935 << ")::createInterface(\"" << interfaceName
936 << "\") returned status = "
937 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800938 }
939 return status;
940 });
941 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800942 LOG(DEBUG) << "Could not create interface \"" << interfaceName << "\". "
943 "Status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800944 }
945 return interface;
946}
947
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700948std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
949 static std::vector<C2Component::Traits> sList{[]() {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800950 std::vector<C2Component::Traits> list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700951 for (Cache& cache : Cache::List()) {
952 std::vector<C2Component::Traits> const& traits = cache.getTraits();
953 list.insert(list.end(), traits.begin(), traits.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800954 }
955 return list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700956 }()};
957 return sList;
958}
Pawin Vongmasa36653902018-11-15 00:10:25 -0800959
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700960std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
961 char const* serviceName) {
Pawin Vongmasaa4ce3882019-05-18 01:52:13 -0700962 int32_t inputSurfaceSetting = ::android::base::GetIntProperty(
963 "debug.stagefright.c2inputsurface", int32_t(0));
964 if (inputSurfaceSetting <= 0) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700965 return nullptr;
966 }
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700967 size_t index = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700968 if (serviceName) {
969 index = getServiceIndex(serviceName);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700970 if (index == GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700971 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
972 << serviceName << "\"";
973 }
974 }
975
976 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700977 if (index != GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700978 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
979 if (client->createInputSurface(&inputSurface) == C2_OK) {
980 return inputSurface;
981 }
982 }
983 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
984 "from all services...";
985 for (Cache& cache : Cache::List()) {
986 std::shared_ptr<Codec2Client> client = cache.getClient();
987 if (client->createInputSurface(&inputSurface) == C2_OK) {
988 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
989 "service \"" << client->getServiceName() << "\"";
990 return inputSurface;
991 }
992 }
993 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
994 "from all services";
995 return nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800996}
997
998// Codec2Client::Listener
999
1000Codec2Client::Listener::~Listener() {
1001}
1002
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001003// Codec2Client::Interface
1004Codec2Client::Interface::Interface(const sp<Base>& base)
1005 : Configurable{
1006 [base]() -> sp<IConfigurable> {
1007 Return<sp<IConfigurable>> transResult =
1008 base->getConfigurable();
1009 return transResult.isOk() ?
1010 static_cast<sp<IConfigurable>>(transResult) :
1011 nullptr;
1012 }()
1013 },
1014 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001015}
1016
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001017// Codec2Client::Component
1018Codec2Client::Component::Component(const sp<Base>& base)
1019 : Configurable{
1020 [base]() -> sp<IConfigurable> {
1021 Return<sp<IComponentInterface>> transResult1 =
1022 base->getInterface();
1023 if (!transResult1.isOk()) {
1024 return nullptr;
1025 }
1026 Return<sp<IConfigurable>> transResult2 =
1027 static_cast<sp<IComponentInterface>>(transResult1)->
1028 getConfigurable();
1029 return transResult2.isOk() ?
1030 static_cast<sp<IConfigurable>>(transResult2) :
1031 nullptr;
1032 }()
1033 },
1034 mBase{base},
1035 mBufferPoolSender{nullptr} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001036}
1037
1038Codec2Client::Component::~Component() {
1039}
1040
1041c2_status_t Codec2Client::Component::createBlockPool(
1042 C2Allocator::id_t id,
1043 C2BlockPool::local_id_t* blockPoolId,
1044 std::shared_ptr<Codec2Client::Configurable>* configurable) {
1045 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001046 Return<void> transStatus = mBase->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001047 static_cast<uint32_t>(id),
1048 [&status, blockPoolId, configurable](
1049 Status s,
1050 uint64_t pId,
1051 const sp<IConfigurable>& c) {
1052 status = static_cast<c2_status_t>(s);
1053 configurable->reset();
1054 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001055 LOG(DEBUG) << "createBlockPool -- call failed: "
1056 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001057 return;
1058 }
1059 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001060 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001061 });
1062 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001063 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001064 return C2_TRANSACTION_FAILED;
1065 }
1066 return status;
1067}
1068
1069c2_status_t Codec2Client::Component::destroyBlockPool(
1070 C2BlockPool::local_id_t localId) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001071 Return<Status> transResult = mBase->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001072 static_cast<uint64_t>(localId));
1073 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001074 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001075 return C2_TRANSACTION_FAILED;
1076 }
1077 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1078}
1079
Wonsik Kimab34ed62019-01-31 15:28:46 -08001080void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001081 const std::list<std::unique_ptr<C2Work>> &workItems) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001082 // Output bufferqueue-based blocks' lifetime management
Sungtak Lee08515812019-06-05 11:16:32 -07001083 mOutputBufferQueue.holdBufferQueueBlocks(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001084}
1085
1086c2_status_t Codec2Client::Component::queue(
1087 std::list<std::unique_ptr<C2Work>>* const items) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001088 WorkBundle workBundle;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001089 if (!objcpy(&workBundle, *items, &mBufferPoolSender)) {
1090 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001091 return C2_TRANSACTION_FAILED;
1092 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001093 Return<Status> transStatus = mBase->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001094 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001095 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001096 return C2_TRANSACTION_FAILED;
1097 }
1098 c2_status_t status =
1099 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1100 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001101 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001102 }
1103 return status;
1104}
1105
1106c2_status_t Codec2Client::Component::flush(
1107 C2Component::flush_mode_t mode,
1108 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
1109 (void)mode; // Flush mode isn't supported in HIDL yet.
1110 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001111 Return<void> transStatus = mBase->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001112 [&status, flushedWork](
1113 Status s, const WorkBundle& wb) {
1114 status = static_cast<c2_status_t>(s);
1115 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001116 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001117 return;
1118 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001119 if (!objcpy(flushedWork, wb)) {
1120 status = C2_CORRUPTED;
1121 } else {
1122 status = C2_OK;
1123 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001124 });
1125 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001126 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001127 return C2_TRANSACTION_FAILED;
1128 }
1129
1130 // Indices of flushed work items.
1131 std::vector<uint64_t> flushedIndices;
1132 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
1133 if (work) {
1134 if (work->worklets.empty()
1135 || !work->worklets.back()
1136 || (work->worklets.back()->output.flags &
1137 C2FrameData::FLAG_INCOMPLETE) == 0) {
1138 // input is complete
1139 flushedIndices.emplace_back(
1140 work->input.ordinal.frameIndex.peeku());
1141 }
1142 }
1143 }
1144
Pawin Vongmasa36653902018-11-15 00:10:25 -08001145 // Output bufferqueue-based blocks' lifetime management
Sungtak Lee08515812019-06-05 11:16:32 -07001146 mOutputBufferQueue.holdBufferQueueBlocks(*flushedWork);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001147
1148 return status;
1149}
1150
1151c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001152 Return<Status> transStatus = mBase->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001153 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1154 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001155 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001156 return C2_TRANSACTION_FAILED;
1157 }
1158 c2_status_t status =
1159 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1160 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001161 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001162 }
1163 return status;
1164}
1165
1166c2_status_t Codec2Client::Component::start() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001167 Return<Status> transStatus = mBase->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001168 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001169 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001170 return C2_TRANSACTION_FAILED;
1171 }
1172 c2_status_t status =
1173 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1174 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001175 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001176 }
1177 return status;
1178}
1179
1180c2_status_t Codec2Client::Component::stop() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001181 Return<Status> transStatus = mBase->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001182 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001183 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001184 return C2_TRANSACTION_FAILED;
1185 }
1186 c2_status_t status =
1187 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1188 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001189 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001190 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001191 return status;
1192}
1193
1194c2_status_t Codec2Client::Component::reset() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001195 Return<Status> transStatus = mBase->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001196 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001197 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001198 return C2_TRANSACTION_FAILED;
1199 }
1200 c2_status_t status =
1201 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1202 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001203 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001204 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001205 return status;
1206}
1207
1208c2_status_t Codec2Client::Component::release() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001209 Return<Status> transStatus = mBase->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001210 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001211 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001212 return C2_TRANSACTION_FAILED;
1213 }
1214 c2_status_t status =
1215 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1216 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001217 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001218 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001219 return status;
1220}
1221
1222c2_status_t Codec2Client::Component::setOutputSurface(
1223 C2BlockPool::local_id_t blockPoolId,
1224 const sp<IGraphicBufferProducer>& surface,
1225 uint32_t generation) {
Sungtak Lee08515812019-06-05 11:16:32 -07001226 uint64_t bqId = 0;
1227 sp<IGraphicBufferProducer> nullIgbp;
1228 sp<HGraphicBufferProducer2> nullHgbp;
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08001229
Sungtak Lee08515812019-06-05 11:16:32 -07001230 sp<HGraphicBufferProducer2> igbp = surface ?
1231 surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
1232 if (surface && !igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001233 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001234 }
1235
Sungtak Lee08515812019-06-05 11:16:32 -07001236 if (!surface) {
1237 mOutputBufferQueue.configure(nullIgbp, generation, 0);
1238 } else if (surface->getUniqueId(&bqId) != OK) {
1239 LOG(ERROR) << "setOutputSurface -- "
1240 "cannot obtain bufferqueue id.";
1241 bqId = 0;
1242 mOutputBufferQueue.configure(nullIgbp, generation, 0);
1243 } else {
1244 mOutputBufferQueue.configure(surface, generation, bqId);
1245 }
1246 ALOGD("generation remote change %u", generation);
1247
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001248 Return<Status> transStatus = mBase->setOutputSurface(
Sungtak Lee08515812019-06-05 11:16:32 -07001249 static_cast<uint64_t>(blockPoolId),
1250 bqId == 0 ? nullHgbp : igbp);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001251 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001252 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001253 return C2_TRANSACTION_FAILED;
1254 }
1255 c2_status_t status =
1256 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1257 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001258 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001259 }
1260 return status;
1261}
1262
1263status_t Codec2Client::Component::queueToOutputSurface(
1264 const C2ConstGraphicBlock& block,
1265 const QueueBufferInput& input,
1266 QueueBufferOutput* output) {
Sungtak Lee08515812019-06-05 11:16:32 -07001267 return mOutputBufferQueue.outputBuffer(block, input, output);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001268}
1269
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001270c2_status_t Codec2Client::Component::connectToInputSurface(
1271 const std::shared_ptr<InputSurface>& inputSurface,
1272 std::shared_ptr<InputSurfaceConnection>* connection) {
1273 c2_status_t status;
1274 Return<void> transStatus = mBase->connectToInputSurface(
1275 inputSurface->mBase,
1276 [&status, connection](
1277 Status s, const sp<IInputSurfaceConnection>& c) {
1278 status = static_cast<c2_status_t>(s);
1279 if (status != C2_OK) {
1280 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1281 << status << ".";
1282 return;
1283 }
1284 *connection = std::make_shared<InputSurfaceConnection>(c);
1285 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001286 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001287 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001288 return C2_TRANSACTION_FAILED;
1289 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001290 return status;
1291}
1292
1293c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001294 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001295 const sp<HGraphicBufferSource>& source,
1296 std::shared_ptr<InputSurfaceConnection>* connection) {
1297 c2_status_t status;
1298 Return<void> transStatus = mBase->connectToOmxInputSurface(
1299 producer, source,
1300 [&status, connection](
1301 Status s, const sp<IInputSurfaceConnection>& c) {
1302 status = static_cast<c2_status_t>(s);
1303 if (status != C2_OK) {
1304 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1305 << status << ".";
1306 return;
1307 }
1308 *connection = std::make_shared<InputSurfaceConnection>(c);
1309 });
1310 if (!transStatus.isOk()) {
1311 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1312 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001313 }
1314 return status;
1315}
1316
1317c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001318 Return<Status> transStatus = mBase->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001319 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001320 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001321 return C2_TRANSACTION_FAILED;
1322 }
1323 c2_status_t status =
1324 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1325 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001326 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1327 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001328 }
1329 return status;
1330}
1331
1332c2_status_t Codec2Client::Component::setDeathListener(
1333 const std::shared_ptr<Component>& component,
1334 const std::shared_ptr<Listener>& listener) {
1335
1336 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1337 std::weak_ptr<Component> component;
1338 std::weak_ptr<Listener> base;
1339
1340 virtual void serviceDied(
1341 uint64_t /* cookie */,
1342 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1343 ) override {
1344 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1345 listener->onDeath(component);
1346 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001347 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001348 }
1349 }
1350 };
1351
1352 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1353 deathRecipient->base = listener;
1354 deathRecipient->component = component;
1355
1356 component->mDeathRecipient = deathRecipient;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001357 Return<bool> transResult = component->mBase->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001358 component->mDeathRecipient, 0);
1359 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001360 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001361 return C2_TRANSACTION_FAILED;
1362 }
1363 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001364 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001365 return C2_CORRUPTED;
1366 }
1367 return C2_OK;
1368}
1369
1370// Codec2Client::InputSurface
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001371Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base)
1372 : Configurable{
1373 [base]() -> sp<IConfigurable> {
1374 Return<sp<IConfigurable>> transResult =
1375 base->getConfigurable();
1376 return transResult.isOk() ?
1377 static_cast<sp<IConfigurable>>(transResult) :
1378 nullptr;
1379 }()
1380 },
1381 mBase{base},
1382 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001383 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
1384 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001385 base->getGraphicBufferProducer();
1386 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001387 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001388 nullptr;
1389 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001390}
1391
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001392sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08001393 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1394 return mGraphicBufferProducer;
1395}
1396
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001397sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001398 return mBase;
1399}
1400
1401// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08001402Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001403 const sp<IInputSurfaceConnection>& base)
1404 : Configurable{
1405 [base]() -> sp<IConfigurable> {
1406 Return<sp<IConfigurable>> transResult =
1407 base->getConfigurable();
1408 return transResult.isOk() ?
1409 static_cast<sp<IConfigurable>>(transResult) :
1410 nullptr;
1411 }()
1412 },
1413 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001414}
1415
1416c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001417 Return<Status> transResult = mBase->disconnect();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001418 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1419}
1420
1421} // namespace android
1422