blob: 199a99c7c55676a6f757346a17dde915ab482425 [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>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070022#include <C2Debug.h>
23#include <C2BufferPriv.h>
24#include <C2PlatformSupport.h>
25
26#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
27#include <android/hardware/media/c2/1.0/IComponent.h>
28#include <android/hardware/media/c2/1.0/IComponentInterface.h>
29#include <android/hardware/media/c2/1.0/IComponentListener.h>
30#include <android/hardware/media/c2/1.0/IComponentStore.h>
31#include <android/hardware/media/c2/1.0/IConfigurable.h>
32#include <android/hidl/manager/1.2/IServiceManager.h>
33
34#include <android-base/properties.h>
35#include <bufferpool/ClientManager.h>
36#include <codec2/hidl/1.0/OutputBufferQueue.h>
37#include <codec2/hidl/1.0/types.h>
38#include <codec2/hidl/1.1/OutputBufferQueue.h>
39#include <codec2/hidl/1.1/types.h>
40
41#include <cutils/native_handle.h>
42#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
43#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
44#include <hidl/HidlSupport.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080045
46#include <deque>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070047#include <iterator>
Pawin Vongmasa36653902018-11-15 00:10:25 -080048#include <limits>
49#include <map>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070050#include <mutex>
51#include <sstream>
52#include <thread>
Pawin Vongmasa36653902018-11-15 00:10:25 -080053#include <type_traits>
54#include <vector>
55
Pawin Vongmasa36653902018-11-15 00:10:25 -080056namespace android {
57
58using ::android::hardware::hidl_vec;
59using ::android::hardware::hidl_string;
60using ::android::hardware::Return;
61using ::android::hardware::Void;
Pawin Vongmasa36653902018-11-15 00:10:25 -080062
Pawin Vongmasabf69de92019-10-29 06:21:27 -070063using namespace ::android::hardware::media::c2::V1_1;
64using namespace ::android::hardware::media::c2::V1_1::utils;
Sungtak Leed3318082018-09-07 15:52:43 -070065using namespace ::android::hardware::media::bufferpool::V2_0;
66using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
Pawin Vongmasa36653902018-11-15 00:10:25 -080067
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080068using HGraphicBufferProducer1 = ::android::hardware::graphics::bufferqueue::
69 V1_0::IGraphicBufferProducer;
70using HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
71 V2_0::IGraphicBufferProducer;
72using B2HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
73 V2_0::utils::B2HGraphicBufferProducer;
74using H2BGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
75 V2_0::utils::H2BGraphicBufferProducer;
76
Pawin Vongmasa36653902018-11-15 00:10:25 -080077namespace /* unnamed */ {
78
79// c2_status_t value that corresponds to hwbinder transaction failure.
80constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
81
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070082// Searches for a name in GetServiceNames() and returns the index found. If the
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070083// name is not found, the returned index will be equal to
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070084// GetServiceNames().size().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070085size_t getServiceIndex(char const* name) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070086 std::vector<std::string> const& names = Codec2Client::GetServiceNames();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070087 size_t i = 0;
88 for (; i < names.size(); ++i) {
89 if (name == names[i]) {
90 break;
91 }
Pawin Vongmasa36653902018-11-15 00:10:25 -080092 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070093 return i;
Pawin Vongmasa36653902018-11-15 00:10:25 -080094}
95
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070096} // unnamed namespace
97
98// This class caches a Codec2Client object and its component traits. The client
99// will be created the first time it is needed, and it can be refreshed if the
100// service dies (by calling invalidate()). The first time listComponents() is
101// called from the client, the result will be cached.
102class Codec2Client::Cache {
103 // Cached client
104 std::shared_ptr<Codec2Client> mClient;
105 mutable std::mutex mClientMutex;
106
107 // Cached component traits
108 std::vector<C2Component::Traits> mTraits;
109 std::once_flag mTraitsInitializationFlag;
110
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700111 // The index of the service. This is based on GetServiceNames().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700112 size_t mIndex;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700113 // Called by s() exactly once to initialize the cache. The index must be a
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700114 // valid index into the vector returned by GetServiceNames(). Calling
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700115 // init(index) will associate the cache to the service with name
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700116 // GetServiceNames()[index].
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700117 void init(size_t index) {
118 mIndex = index;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700119 }
120
121public:
122 Cache() = default;
123
124 // Initializes mClient if needed, then returns mClient.
125 // If the service is unavailable but listed in the manifest, this function
126 // will block indefinitely.
127 std::shared_ptr<Codec2Client> getClient() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700128 std::scoped_lock lock{mClientMutex};
129 if (!mClient) {
130 mClient = Codec2Client::_CreateFromIndex(mIndex);
131 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700132 CHECK(mClient) << "Failed to create Codec2Client to service \""
133 << GetServiceNames()[mIndex] << "\". (Index = "
134 << mIndex << ").";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700135 return mClient;
136 }
137
138 // Causes a subsequent call to getClient() to create a new client. This
139 // function should be called after the service dies.
140 //
141 // Note: This function is called only by ForAllServices().
142 void invalidate() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700143 std::scoped_lock lock{mClientMutex};
144 mClient = nullptr;
145 }
146
147 // Returns a list of traits for components supported by the service. This
148 // list is cached.
149 std::vector<C2Component::Traits> const& getTraits() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700150 std::call_once(mTraitsInitializationFlag, [this]() {
151 bool success{false};
152 // Spin until _listComponents() is successful.
153 while (true) {
154 std::shared_ptr<Codec2Client> client = getClient();
155 mTraits = client->_listComponents(&success);
156 if (success) {
157 break;
158 }
159 using namespace std::chrono_literals;
160 static constexpr auto kServiceRetryPeriod = 5s;
161 LOG(INFO) << "Failed to retrieve component traits from service "
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700162 "\"" << GetServiceNames()[mIndex] << "\". "
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700163 "Retrying...";
164 std::this_thread::sleep_for(kServiceRetryPeriod);
165 }
166 });
167 return mTraits;
168 }
169
170 // List() returns the list of all caches.
171 static std::vector<Cache>& List() {
172 static std::vector<Cache> sCaches{[]() {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700173 size_t numServices = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700174 std::vector<Cache> caches(numServices);
175 for (size_t i = 0; i < numServices; ++i) {
176 caches[i].init(i);
177 }
178 return caches;
179 }()};
180 return sCaches;
181 }
182};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800183
184// Codec2ConfigurableClient
185
186const C2String& Codec2ConfigurableClient::getName() const {
187 return mName;
188}
189
Pawin Vongmasa36653902018-11-15 00:10:25 -0800190Codec2ConfigurableClient::Codec2ConfigurableClient(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800191 const sp<IConfigurable>& base)
192 : mBase{base},
193 mName{[base]() -> C2String {
194 C2String outName;
195 Return<void> transStatus = base->getName(
196 [&outName](const hidl_string& name) {
197 outName = name.c_str();
198 });
199 return transStatus.isOk() ? outName : "";
200 }()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800201}
202
203c2_status_t Codec2ConfigurableClient::query(
204 const std::vector<C2Param*> &stackParams,
205 const std::vector<C2Param::Index> &heapParamIndices,
206 c2_blocking_t mayBlock,
207 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
208 hidl_vec<ParamIndex> indices(
209 stackParams.size() + heapParamIndices.size());
210 size_t numIndices = 0;
211 for (C2Param* const& stackParam : stackParams) {
212 if (!stackParam) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800213 LOG(WARNING) << "query -- null stack param encountered.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800214 continue;
215 }
216 indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
217 }
218 size_t numStackIndices = numIndices;
219 for (const C2Param::Index& index : heapParamIndices) {
220 indices[numIndices++] =
221 static_cast<ParamIndex>(static_cast<uint32_t>(index));
222 }
223 indices.resize(numIndices);
224 if (heapParams) {
225 heapParams->reserve(heapParams->size() + numIndices);
226 }
227 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800228 Return<void> transStatus = mBase->query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800229 indices,
230 mayBlock == C2_MAY_BLOCK,
231 [&status, &numStackIndices, &stackParams, heapParams](
232 Status s, const Params& p) {
233 status = static_cast<c2_status_t>(s);
234 if (status != C2_OK && status != C2_BAD_INDEX) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800235 LOG(DEBUG) << "query -- call failed: "
236 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800237 return;
238 }
239 std::vector<C2Param*> paramPointers;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800240 if (!parseParamsBlob(&paramPointers, p)) {
241 LOG(ERROR) << "query -- error while parsing params.";
242 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800243 return;
244 }
245 size_t i = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800246 for (auto it = paramPointers.begin();
247 it != paramPointers.end(); ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800248 C2Param* paramPointer = *it;
249 if (numStackIndices > 0) {
250 --numStackIndices;
251 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800252 LOG(WARNING) << "query -- null stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800253 ++it;
254 continue;
255 }
256 for (; i < stackParams.size() && !stackParams[i]; ) {
257 ++i;
258 }
259 if (i >= stackParams.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800260 LOG(ERROR) << "query -- unexpected error.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800261 status = C2_CORRUPTED;
262 return;
263 }
264 if (stackParams[i]->index() != paramPointer->index()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800265 LOG(WARNING) << "query -- param skipped: "
266 "index = "
267 << stackParams[i]->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800268 stackParams[i++]->invalidate();
269 continue;
270 }
271 if (!stackParams[i++]->updateFrom(*paramPointer)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800272 LOG(WARNING) << "query -- param update failed: "
273 "index = "
274 << paramPointer->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800275 }
276 } else {
277 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800278 LOG(WARNING) << "query -- null heap param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800279 ++it;
280 continue;
281 }
282 if (!heapParams) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800283 LOG(WARNING) << "query -- "
284 "unexpected extra stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800285 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800286 heapParams->emplace_back(
287 C2Param::Copy(*paramPointer));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800288 }
289 }
290 ++it;
291 }
292 });
293 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800294 LOG(ERROR) << "query -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800295 return C2_TRANSACTION_FAILED;
296 }
297 return status;
298}
299
300c2_status_t Codec2ConfigurableClient::config(
301 const std::vector<C2Param*> &params,
302 c2_blocking_t mayBlock,
303 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
304 Params hidlParams;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800305 if (!createParamsBlob(&hidlParams, params)) {
306 LOG(ERROR) << "config -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800307 return C2_TRANSACTION_FAILED;
308 }
309 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800310 Return<void> transStatus = mBase->config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800311 hidlParams,
312 mayBlock == C2_MAY_BLOCK,
313 [&status, &params, failures](
314 Status s,
315 const hidl_vec<SettingResult> f,
316 const Params& o) {
317 status = static_cast<c2_status_t>(s);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800318 if (status != C2_OK && status != C2_BAD_INDEX) {
319 LOG(DEBUG) << "config -- call failed: "
320 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800321 }
322 size_t i = failures->size();
323 failures->resize(i + f.size());
324 for (const SettingResult& sf : f) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800325 if (!objcpy(&(*failures)[i++], sf)) {
326 LOG(ERROR) << "config -- "
327 << "invalid SettingResult returned.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800328 return;
329 }
330 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800331 if (!updateParamsFromBlob(params, o)) {
332 LOG(ERROR) << "config -- "
333 << "failed to parse returned params.";
334 status = C2_CORRUPTED;
335 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800336 });
337 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800338 LOG(ERROR) << "config -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800339 return C2_TRANSACTION_FAILED;
340 }
341 return status;
342}
343
344c2_status_t Codec2ConfigurableClient::querySupportedParams(
345 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
346 // TODO: Cache and query properly!
347 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800348 Return<void> transStatus = mBase->querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800349 std::numeric_limits<uint32_t>::min(),
350 std::numeric_limits<uint32_t>::max(),
351 [&status, params](
352 Status s,
353 const hidl_vec<ParamDescriptor>& p) {
354 status = static_cast<c2_status_t>(s);
355 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800356 LOG(DEBUG) << "querySupportedParams -- call failed: "
357 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800358 return;
359 }
360 size_t i = params->size();
361 params->resize(i + p.size());
362 for (const ParamDescriptor& sp : p) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800363 if (!objcpy(&(*params)[i++], sp)) {
364 LOG(ERROR) << "querySupportedParams -- "
365 << "invalid returned ParamDescriptor.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800366 return;
367 }
368 }
369 });
370 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800371 LOG(ERROR) << "querySupportedParams -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800372 return C2_TRANSACTION_FAILED;
373 }
374 return status;
375}
376
377c2_status_t Codec2ConfigurableClient::querySupportedValues(
378 std::vector<C2FieldSupportedValuesQuery>& fields,
379 c2_blocking_t mayBlock) const {
380 hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
381 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800382 if (!objcpy(&inFields[i], fields[i])) {
383 LOG(ERROR) << "querySupportedValues -- bad input";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800384 return C2_TRANSACTION_FAILED;
385 }
386 }
387
388 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800389 Return<void> transStatus = mBase->querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800390 inFields,
391 mayBlock == C2_MAY_BLOCK,
392 [&status, &inFields, &fields](
393 Status s,
394 const hidl_vec<FieldSupportedValuesQueryResult>& r) {
395 status = static_cast<c2_status_t>(s);
396 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800397 LOG(DEBUG) << "querySupportedValues -- call failed: "
398 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800399 return;
400 }
401 if (r.size() != fields.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800402 LOG(ERROR) << "querySupportedValues -- "
403 "input and output lists "
404 "have different sizes.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800405 status = C2_CORRUPTED;
406 return;
407 }
408 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800409 if (!objcpy(&fields[i], inFields[i], r[i])) {
410 LOG(ERROR) << "querySupportedValues -- "
411 "invalid returned value.";
412 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800413 return;
414 }
415 }
416 });
417 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800418 LOG(ERROR) << "querySupportedValues -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800419 return C2_TRANSACTION_FAILED;
420 }
421 return status;
422}
423
424// Codec2Client::Component::HidlListener
425struct Codec2Client::Component::HidlListener : public IComponentListener {
426 std::weak_ptr<Component> component;
427 std::weak_ptr<Listener> base;
428
429 virtual Return<void> onWorkDone(const WorkBundle& workBundle) override {
430 std::list<std::unique_ptr<C2Work>> workItems;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800431 if (!objcpy(&workItems, workBundle)) {
432 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800433 return Void();
434 }
435 // release input buffers potentially held by the component from queue
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800436 std::shared_ptr<Codec2Client::Component> strongComponent =
437 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800438 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800439 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800440 }
441 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800442 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800443 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800444 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800445 }
446 return Void();
447 }
448
449 virtual Return<void> onTripped(
450 const hidl_vec<SettingResult>& settingResults) override {
451 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
452 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800453 for (size_t i = 0; i < settingResults.size(); ++i) {
454 std::unique_ptr<C2SettingResult> c2SettingResult;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800455 if (!objcpy(&c2SettingResult, settingResults[i])) {
456 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800457 return Void();
458 }
459 c2SettingResults[i] = std::move(c2SettingResult);
460 }
461 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
462 listener->onTripped(component, c2SettingResults);
463 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800464 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800465 }
466 return Void();
467 }
468
469 virtual Return<void> onError(Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800470 LOG(DEBUG) << "onError --"
471 << " status = " << s
472 << ", errorCode = " << errorCode
473 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800474 if (std::shared_ptr<Listener> listener = base.lock()) {
475 listener->onError(component, s == Status::OK ?
476 errorCode : static_cast<c2_status_t>(s));
477 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800478 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800479 }
480 return Void();
481 }
482
483 virtual Return<void> onFramesRendered(
484 const hidl_vec<RenderedFrame>& renderedFrames) override {
485 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800486 if (!listener) {
487 LOG(DEBUG) << "onFramesRendered -- listener died.";
488 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800489 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800490 for (const RenderedFrame& renderedFrame : renderedFrames) {
491 listener->onFrameRendered(
492 renderedFrame.bufferQueueId,
493 renderedFrame.slotId,
494 renderedFrame.timestampNs);
495 }
496 return Void();
497 }
498
499 virtual Return<void> onInputBuffersReleased(
500 const hidl_vec<InputBuffer>& inputBuffers) override {
501 std::shared_ptr<Listener> listener = base.lock();
502 if (!listener) {
503 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
504 return Void();
505 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800506 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800507 LOG(VERBOSE) << "onInputBuffersReleased --"
508 " received death notification of"
509 " input buffer:"
510 " frameIndex = " << inputBuffer.frameIndex
511 << ", bufferIndex = " << inputBuffer.arrayIndex
512 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -0800513 listener->onInputBufferDone(
514 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800515 }
516 return Void();
517 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800518
Pawin Vongmasa36653902018-11-15 00:10:25 -0800519};
520
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700521// Codec2Client::Component::BufferPoolSender
522struct Codec2Client::Component::BufferPoolSender :
523 hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
524 BufferPoolSender()
525 : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
526 }
527};
528
529// Codec2Client::Component::OutputBufferQueue
530struct Codec2Client::Component::OutputBufferQueue :
531 hardware::media::c2::V1_1::utils::OutputBufferQueue {
532 OutputBufferQueue()
533 : hardware::media::c2::V1_1::utils::OutputBufferQueue() {
534 }
535};
536
Pawin Vongmasa36653902018-11-15 00:10:25 -0800537// Codec2Client
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700538Codec2Client::Codec2Client(sp<Base> const& base,
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700539 size_t serviceIndex)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800540 : Configurable{
541 [base]() -> sp<IConfigurable> {
542 Return<sp<IConfigurable>> transResult =
543 base->getConfigurable();
544 return transResult.isOk() ?
545 static_cast<sp<IConfigurable>>(transResult) :
546 nullptr;
547 }()
548 },
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700549 mBase1_0{base},
550 mBase1_1{Base1_1::castFrom(base)},
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700551 mServiceIndex{serviceIndex} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800552 Return<sp<IClientManager>> transResult = base->getPoolClientManager();
553 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800554 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800555 } else {
556 mHostPoolManager = static_cast<sp<IClientManager>>(transResult);
557 }
558}
559
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700560sp<Codec2Client::Base> const& Codec2Client::getBase() const {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700561 return mBase1_0;
562}
563
564sp<Codec2Client::Base1_0> const& Codec2Client::getBase1_0() const {
565 return mBase1_0;
566}
567
568sp<Codec2Client::Base1_1> const& Codec2Client::getBase1_1() const {
569 return mBase1_1;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700570}
571
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700572std::string const& Codec2Client::getServiceName() const {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700573 return GetServiceNames()[mServiceIndex];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700574}
575
Pawin Vongmasa36653902018-11-15 00:10:25 -0800576c2_status_t Codec2Client::createComponent(
577 const C2String& name,
578 const std::shared_ptr<Codec2Client::Listener>& listener,
579 std::shared_ptr<Codec2Client::Component>* const component) {
580
Pawin Vongmasa36653902018-11-15 00:10:25 -0800581 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800582 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800583 hidlListener->base = listener;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700584 Return<void> transStatus = mBase1_1 ?
585 mBase1_1->createComponent_1_1(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800586 name,
587 hidlListener,
588 ClientManager::getInstance(),
589 [&status, component, hidlListener](
590 Status s,
591 const sp<IComponent>& c) {
592 status = static_cast<c2_status_t>(s);
593 if (status != C2_OK) {
594 return;
595 }
596 *component = std::make_shared<Codec2Client::Component>(c);
597 hidlListener->component = *component;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700598 }) :
599 mBase1_0->createComponent(
600 name,
601 hidlListener,
602 ClientManager::getInstance(),
603 [&status, component, hidlListener](
604 Status s,
605 const sp<hardware::media::c2::V1_0::IComponent>& c) {
606 status = static_cast<c2_status_t>(s);
607 if (status != C2_OK) {
608 return;
609 }
610 *component = std::make_shared<Codec2Client::Component>(c);
611 hidlListener->component = *component;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800612 });
613 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800614 LOG(ERROR) << "createComponent(" << name.c_str()
615 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800616 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800617 } else if (status != C2_OK) {
618 LOG(ERROR) << "createComponent(" << name.c_str()
619 << ") -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800620 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800621 } else if (!*component) {
622 LOG(ERROR) << "createComponent(" << name.c_str()
623 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800624 return C2_CORRUPTED;
625 }
626
627 status = (*component)->setDeathListener(*component, listener);
628 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800629 LOG(ERROR) << "createComponent(" << name.c_str()
630 << ") -- failed to set up death listener: "
631 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800632 }
633
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700634 (*component)->mBufferPoolSender->setReceiver(mHostPoolManager);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800635 return status;
636}
637
638c2_status_t Codec2Client::createInterface(
639 const C2String& name,
640 std::shared_ptr<Codec2Client::Interface>* const interface) {
641 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700642 Return<void> transStatus = mBase1_0->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800643 name,
644 [&status, interface](
645 Status s,
646 const sp<IComponentInterface>& i) {
647 status = static_cast<c2_status_t>(s);
648 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800649 return;
650 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800651 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800652 });
653 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800654 LOG(ERROR) << "createInterface(" << name.c_str()
655 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800656 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800657 } else if (status != C2_OK) {
658 LOG(ERROR) << "createComponent(" << name.c_str()
659 << ") -- call failed: " << status << ".";
660 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800661 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800662
Pawin Vongmasa36653902018-11-15 00:10:25 -0800663 return status;
664}
665
666c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800667 std::shared_ptr<InputSurface>* const inputSurface) {
668 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700669 Return<void> transStatus = mBase1_0->createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800670 [&status, inputSurface](
671 Status s,
672 const sp<IInputSurface>& i) {
673 status = static_cast<c2_status_t>(s);
674 if (status != C2_OK) {
675 return;
676 }
677 *inputSurface = std::make_shared<InputSurface>(i);
678 });
679 if (!transStatus.isOk()) {
680 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800681 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800682 } else if (status != C2_OK) {
683 LOG(DEBUG) << "createInputSurface -- call failed: "
684 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800685 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800686 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800687}
688
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700689std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
690 return Cache::List()[mServiceIndex].getTraits();
691}
692
693std::vector<C2Component::Traits> Codec2Client::_listComponents(
694 bool* success) const {
695 std::vector<C2Component::Traits> traits;
696 std::string const& serviceName = getServiceName();
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700697 Return<void> transStatus = mBase1_0->listComponents(
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700698 [&traits, &serviceName](Status s,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800699 const hidl_vec<IComponentStore::ComponentTraits>& t) {
700 if (s != Status::OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700701 LOG(DEBUG) << "_listComponents -- call failed: "
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800702 << static_cast<c2_status_t>(s) << ".";
703 return;
704 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700705 traits.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800706 for (size_t i = 0; i < t.size(); ++i) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700707 if (!objcpy(&traits[i], t[i])) {
708 LOG(ERROR) << "_listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800709 return;
710 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700711 traits[i].owner = serviceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800712 }
713 });
714 if (!transStatus.isOk()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700715 LOG(ERROR) << "_listComponents -- transaction failed.";
716 *success = false;
717 } else {
718 *success = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800719 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700720 return traits;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800721}
722
723c2_status_t Codec2Client::copyBuffer(
724 const std::shared_ptr<C2Buffer>& src,
725 const std::shared_ptr<C2Buffer>& dst) {
726 // TODO: Implement?
727 (void)src;
728 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800729 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800730 return C2_OMITTED;
731}
732
733std::shared_ptr<C2ParamReflector>
734 Codec2Client::getParamReflector() {
735 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
736 // should reflect the HAL API.
737 struct SimpleParamReflector : public C2ParamReflector {
738 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
739 hidl_vec<ParamIndex> indices(1);
740 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
741 std::unique_ptr<C2StructDescriptor> descriptor;
742 Return<void> transStatus = mBase->getStructDescriptors(
743 indices,
744 [&descriptor](
745 Status s,
746 const hidl_vec<StructDescriptor>& sd) {
747 c2_status_t status = static_cast<c2_status_t>(s);
748 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800749 LOG(DEBUG) << "SimpleParamReflector -- "
750 "getStructDescriptors() failed: "
751 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800752 descriptor.reset();
753 return;
754 }
755 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800756 LOG(DEBUG) << "SimpleParamReflector -- "
757 "getStructDescriptors() "
758 "returned vector of size "
759 << sd.size() << ". "
760 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800761 descriptor.reset();
762 return;
763 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800764 if (!objcpy(&descriptor, sd[0])) {
765 LOG(DEBUG) << "SimpleParamReflector -- "
766 "getStructDescriptors() returned "
767 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800768 descriptor.reset();
769 return;
770 }
771 });
772 return descriptor;
773 }
774
775 SimpleParamReflector(sp<Base> base)
776 : mBase(base) { }
777
778 sp<Base> mBase;
779 };
780
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700781 return std::make_shared<SimpleParamReflector>(mBase1_0);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800782};
783
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700784std::vector<std::string> const& Codec2Client::GetServiceNames() {
785 static std::vector<std::string> sServiceNames{[]() {
786 using ::android::hardware::media::c2::V1_0::IComponentStore;
787 using ::android::hidl::manager::V1_2::IServiceManager;
788
789 while (true) {
790 sp<IServiceManager> serviceManager = IServiceManager::getService();
791 CHECK(serviceManager) << "Hardware service manager is not running.";
792
793 // There are three categories of services based on names.
794 std::vector<std::string> defaultNames; // Prefixed with "default"
795 std::vector<std::string> vendorNames; // Prefixed with "vendor"
796 std::vector<std::string> otherNames; // Others
797 Return<void> transResult;
798 transResult = serviceManager->listManifestByInterface(
799 IComponentStore::descriptor,
800 [&defaultNames, &vendorNames, &otherNames](
801 hidl_vec<hidl_string> const& instanceNames) {
802 for (hidl_string const& instanceName : instanceNames) {
803 char const* name = instanceName.c_str();
804 if (strncmp(name, "default", 7) == 0) {
805 defaultNames.emplace_back(name);
806 } else if (strncmp(name, "vendor", 6) == 0) {
807 vendorNames.emplace_back(name);
808 } else {
809 otherNames.emplace_back(name);
810 }
811 }
812 });
813 if (transResult.isOk()) {
814 // Sort service names in each category.
815 std::sort(defaultNames.begin(), defaultNames.end());
816 std::sort(vendorNames.begin(), vendorNames.end());
817 std::sort(otherNames.begin(), otherNames.end());
818
819 // Concatenate the three lists in this order: default, vendor,
820 // other.
821 std::vector<std::string>& names = defaultNames;
822 names.reserve(names.size() + vendorNames.size() + otherNames.size());
823 names.insert(names.end(),
824 std::make_move_iterator(vendorNames.begin()),
825 std::make_move_iterator(vendorNames.end()));
826 names.insert(names.end(),
827 std::make_move_iterator(otherNames.begin()),
828 std::make_move_iterator(otherNames.end()));
829
830 // Summarize to logcat.
831 if (names.empty()) {
832 LOG(INFO) << "No Codec2 services declared in the manifest.";
833 } else {
834 std::stringstream stringOutput;
835 stringOutput << "Available Codec2 services:";
836 for (std::string const& name : names) {
837 stringOutput << " \"" << name << "\"";
838 }
839 LOG(INFO) << stringOutput.str();
840 }
841
842 return names;
843 }
844 LOG(ERROR) << "Could not retrieve the list of service instances of "
845 << IComponentStore::descriptor
846 << ". Retrying...";
847 }
848 }()};
849 return sServiceNames;
850}
851
Pawin Vongmasa36653902018-11-15 00:10:25 -0800852std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700853 const char* name) {
854 size_t index = getServiceIndex(name);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700855 return index == GetServiceNames().size() ?
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700856 nullptr : _CreateFromIndex(index);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800857}
858
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700859std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
860 CreateFromAllServices() {
861 std::vector<std::shared_ptr<Codec2Client>> clients(
862 GetServiceNames().size());
863 for (size_t i = GetServiceNames().size(); i > 0; ) {
864 --i;
865 clients[i] = _CreateFromIndex(i);
866 }
867 return clients;
868}
869
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700870std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700871 std::string const& name = GetServiceNames()[index];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700872 LOG(INFO) << "Creating a Codec2 client to service \"" << name << "\"";
873 sp<Base> baseStore = Base::getService(name);
874 CHECK(baseStore) << "Codec2 service \"" << name << "\""
875 " inaccessible for unknown reasons.";
876 LOG(INFO) << "Client to Codec2 service \"" << name << "\" created";
877 return std::make_shared<Codec2Client>(baseStore, index);
878}
879
880c2_status_t Codec2Client::ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800881 const std::string &key,
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700882 size_t numberOfAttempts,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800883 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
884 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800885 c2_status_t status = C2_NO_INIT; // no IComponentStores present
886
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700887 // Cache the mapping key -> index of Codec2Client in Cache::List().
Pawin Vongmasa36653902018-11-15 00:10:25 -0800888 static std::mutex key2IndexMutex;
889 static std::map<std::string, size_t> key2Index;
890
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800891 // By default try all stores. However, try the last known client first. If
892 // the last known client fails, retry once. We do this by pushing the last
893 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800894 std::deque<size_t> indices;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700895 for (size_t index = Cache::List().size(); index > 0; ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800896 indices.push_front(--index);
897 }
898
899 bool wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700900 {
901 std::scoped_lock lock{key2IndexMutex};
902 auto it = key2Index.find(key);
903 if (it != key2Index.end()) {
904 indices.push_front(it->second);
905 wasMapped = true;
906 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800907 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800908
909 for (size_t index : indices) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700910 Cache& cache = Cache::List()[index];
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700911 for (size_t tries = numberOfAttempts; tries > 0; --tries) {
912 std::shared_ptr<Codec2Client> client{cache.getClient()};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800913 status = predicate(client);
914 if (status == C2_OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700915 std::scoped_lock lock{key2IndexMutex};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800916 key2Index[key] = index; // update last known client index
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700917 return C2_OK;
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700918 } else if (status == C2_TRANSACTION_FAILED) {
919 LOG(WARNING) << "\"" << key << "\" failed for service \""
920 << client->getName()
921 << "\" due to transaction failure. "
922 << "(Service may have crashed.)"
923 << (tries > 1 ? " Retrying..." : "");
924 cache.invalidate();
925 continue;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800926 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700927 if (wasMapped) {
928 LOG(INFO) << "\"" << key << "\" became invalid in service \""
929 << client->getName() << "\". Retrying...";
930 wasMapped = false;
931 }
932 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800933 }
934 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700935 return status; // return the last status from a valid client
Pawin Vongmasa36653902018-11-15 00:10:25 -0800936}
937
938std::shared_ptr<Codec2Client::Component>
939 Codec2Client::CreateComponentByName(
940 const char* componentName,
941 const std::shared_ptr<Listener>& listener,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -0700942 std::shared_ptr<Codec2Client>* owner,
943 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700944 std::string key{"create:"};
945 key.append(componentName);
946 std::shared_ptr<Component> component;
947 c2_status_t status = ForAllServices(
948 key,
949 numberOfAttempts,
950 [owner, &component, componentName, &listener](
951 const std::shared_ptr<Codec2Client> &client)
952 -> c2_status_t {
953 c2_status_t status = client->createComponent(componentName,
954 listener,
955 &component);
956 if (status == C2_OK) {
957 if (owner) {
958 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800959 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700960 } else if (status != C2_NOT_FOUND) {
961 LOG(DEBUG) << "IComponentStore("
962 << client->getServiceName()
963 << ")::createComponent(\"" << componentName
964 << "\") returned status = "
965 << status << ".";
966 }
967 return status;
968 });
969 if (status != C2_OK) {
970 LOG(DEBUG) << "Failed to create component \"" << componentName
971 << "\" from all known services. "
972 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800973 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700974 return component;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800975}
976
977std::shared_ptr<Codec2Client::Interface>
978 Codec2Client::CreateInterfaceByName(
979 const char* interfaceName,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -0700980 std::shared_ptr<Codec2Client>* owner,
981 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700982 std::string key{"create:"};
983 key.append(interfaceName);
984 std::shared_ptr<Interface> interface;
985 c2_status_t status = ForAllServices(
986 key,
987 numberOfAttempts,
988 [owner, &interface, interfaceName](
989 const std::shared_ptr<Codec2Client> &client)
990 -> c2_status_t {
991 c2_status_t status = client->createInterface(interfaceName,
992 &interface);
993 if (status == C2_OK) {
994 if (owner) {
995 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800996 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700997 } else if (status != C2_NOT_FOUND) {
998 LOG(DEBUG) << "IComponentStore("
999 << client->getServiceName()
1000 << ")::createInterface(\"" << interfaceName
1001 << "\") returned status = "
1002 << status << ".";
1003 }
1004 return status;
1005 });
1006 if (status != C2_OK) {
1007 LOG(DEBUG) << "Failed to create interface \"" << interfaceName
1008 << "\" from all known services. "
1009 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001010 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001011 return interface;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001012}
1013
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001014std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
1015 static std::vector<C2Component::Traits> sList{[]() {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001016 std::vector<C2Component::Traits> list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001017 for (Cache& cache : Cache::List()) {
1018 std::vector<C2Component::Traits> const& traits = cache.getTraits();
1019 list.insert(list.end(), traits.begin(), traits.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001020 }
1021 return list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001022 }()};
1023 return sList;
1024}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001025
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001026std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
1027 char const* serviceName) {
Pawin Vongmasa18588322019-05-18 01:52:13 -07001028 int32_t inputSurfaceSetting = ::android::base::GetIntProperty(
1029 "debug.stagefright.c2inputsurface", int32_t(0));
1030 if (inputSurfaceSetting <= 0) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001031 return nullptr;
1032 }
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001033 size_t index = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001034 if (serviceName) {
1035 index = getServiceIndex(serviceName);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001036 if (index == GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001037 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
1038 << serviceName << "\"";
1039 }
1040 }
1041
1042 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001043 if (index != GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001044 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
1045 if (client->createInputSurface(&inputSurface) == C2_OK) {
1046 return inputSurface;
1047 }
1048 }
1049 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
1050 "from all services...";
1051 for (Cache& cache : Cache::List()) {
1052 std::shared_ptr<Codec2Client> client = cache.getClient();
1053 if (client->createInputSurface(&inputSurface) == C2_OK) {
1054 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
1055 "service \"" << client->getServiceName() << "\"";
1056 return inputSurface;
1057 }
1058 }
1059 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
1060 "from all services";
1061 return nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001062}
1063
1064// Codec2Client::Listener
1065
1066Codec2Client::Listener::~Listener() {
1067}
1068
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001069// Codec2Client::Interface
1070Codec2Client::Interface::Interface(const sp<Base>& base)
1071 : Configurable{
1072 [base]() -> sp<IConfigurable> {
1073 Return<sp<IConfigurable>> transResult =
1074 base->getConfigurable();
1075 return transResult.isOk() ?
1076 static_cast<sp<IConfigurable>>(transResult) :
1077 nullptr;
1078 }()
1079 },
1080 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001081}
1082
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001083// Codec2Client::Component
1084Codec2Client::Component::Component(const sp<Base>& base)
1085 : Configurable{
1086 [base]() -> sp<IConfigurable> {
1087 Return<sp<IComponentInterface>> transResult1 =
1088 base->getInterface();
1089 if (!transResult1.isOk()) {
1090 return nullptr;
1091 }
1092 Return<sp<IConfigurable>> transResult2 =
1093 static_cast<sp<IComponentInterface>>(transResult1)->
1094 getConfigurable();
1095 return transResult2.isOk() ?
1096 static_cast<sp<IConfigurable>>(transResult2) :
1097 nullptr;
1098 }()
1099 },
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001100 mBase1_0{base},
1101 mBase1_1{Base1_1::castFrom(base)},
1102 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1103 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1104}
1105
1106Codec2Client::Component::Component(const sp<Base1_1>& base)
1107 : Configurable{
1108 [base]() -> sp<IConfigurable> {
1109 Return<sp<IComponentInterface>> transResult1 =
1110 base->getInterface();
1111 if (!transResult1.isOk()) {
1112 return nullptr;
1113 }
1114 Return<sp<IConfigurable>> transResult2 =
1115 static_cast<sp<IComponentInterface>>(transResult1)->
1116 getConfigurable();
1117 return transResult2.isOk() ?
1118 static_cast<sp<IConfigurable>>(transResult2) :
1119 nullptr;
1120 }()
1121 },
1122 mBase1_0{base},
1123 mBase1_1{base},
1124 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1125 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001126}
1127
1128Codec2Client::Component::~Component() {
1129}
1130
1131c2_status_t Codec2Client::Component::createBlockPool(
1132 C2Allocator::id_t id,
1133 C2BlockPool::local_id_t* blockPoolId,
1134 std::shared_ptr<Codec2Client::Configurable>* configurable) {
1135 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001136 Return<void> transStatus = mBase1_0->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001137 static_cast<uint32_t>(id),
1138 [&status, blockPoolId, configurable](
1139 Status s,
1140 uint64_t pId,
1141 const sp<IConfigurable>& c) {
1142 status = static_cast<c2_status_t>(s);
1143 configurable->reset();
1144 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001145 LOG(DEBUG) << "createBlockPool -- call failed: "
1146 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001147 return;
1148 }
1149 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001150 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001151 });
1152 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001153 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001154 return C2_TRANSACTION_FAILED;
1155 }
1156 return status;
1157}
1158
1159c2_status_t Codec2Client::Component::destroyBlockPool(
1160 C2BlockPool::local_id_t localId) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001161 Return<Status> transResult = mBase1_0->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001162 static_cast<uint64_t>(localId));
1163 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001164 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001165 return C2_TRANSACTION_FAILED;
1166 }
1167 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1168}
1169
Wonsik Kimab34ed62019-01-31 15:28:46 -08001170void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001171 const std::list<std::unique_ptr<C2Work>> &workItems) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001172 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001173 mOutputBufferQueue->holdBufferQueueBlocks(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001174}
1175
1176c2_status_t Codec2Client::Component::queue(
1177 std::list<std::unique_ptr<C2Work>>* const items) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001178 WorkBundle workBundle;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001179 if (!objcpy(&workBundle, *items, mBufferPoolSender.get())) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001180 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001181 return C2_TRANSACTION_FAILED;
1182 }
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001183 Return<Status> transStatus = mBase1_0->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001184 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001185 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001186 return C2_TRANSACTION_FAILED;
1187 }
1188 c2_status_t status =
1189 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1190 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001191 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001192 }
1193 return status;
1194}
1195
1196c2_status_t Codec2Client::Component::flush(
1197 C2Component::flush_mode_t mode,
1198 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
1199 (void)mode; // Flush mode isn't supported in HIDL yet.
1200 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001201 Return<void> transStatus = mBase1_0->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001202 [&status, flushedWork](
1203 Status s, const WorkBundle& wb) {
1204 status = static_cast<c2_status_t>(s);
1205 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001206 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001207 return;
1208 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001209 if (!objcpy(flushedWork, wb)) {
1210 status = C2_CORRUPTED;
1211 } else {
1212 status = C2_OK;
1213 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001214 });
1215 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001216 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001217 return C2_TRANSACTION_FAILED;
1218 }
1219
1220 // Indices of flushed work items.
1221 std::vector<uint64_t> flushedIndices;
1222 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
1223 if (work) {
1224 if (work->worklets.empty()
1225 || !work->worklets.back()
1226 || (work->worklets.back()->output.flags &
1227 C2FrameData::FLAG_INCOMPLETE) == 0) {
1228 // input is complete
1229 flushedIndices.emplace_back(
1230 work->input.ordinal.frameIndex.peeku());
1231 }
1232 }
1233 }
1234
Pawin Vongmasa36653902018-11-15 00:10:25 -08001235 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001236 mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001237
1238 return status;
1239}
1240
1241c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001242 Return<Status> transStatus = mBase1_0->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001243 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1244 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001245 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001246 return C2_TRANSACTION_FAILED;
1247 }
1248 c2_status_t status =
1249 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1250 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001251 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001252 }
1253 return status;
1254}
1255
1256c2_status_t Codec2Client::Component::start() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001257 Return<Status> transStatus = mBase1_0->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001258 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001259 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001260 return C2_TRANSACTION_FAILED;
1261 }
1262 c2_status_t status =
1263 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1264 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001265 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001266 }
1267 return status;
1268}
1269
1270c2_status_t Codec2Client::Component::stop() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001271 Return<Status> transStatus = mBase1_0->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001272 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001273 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001274 return C2_TRANSACTION_FAILED;
1275 }
1276 c2_status_t status =
1277 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1278 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001279 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001280 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001281 return status;
1282}
1283
1284c2_status_t Codec2Client::Component::reset() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001285 Return<Status> transStatus = mBase1_0->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001286 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001287 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001288 return C2_TRANSACTION_FAILED;
1289 }
1290 c2_status_t status =
1291 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1292 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001293 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001294 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001295 return status;
1296}
1297
1298c2_status_t Codec2Client::Component::release() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001299 Return<Status> transStatus = mBase1_0->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001300 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001301 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001302 return C2_TRANSACTION_FAILED;
1303 }
1304 c2_status_t status =
1305 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1306 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001307 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001308 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001309 return status;
1310}
1311
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001312c2_status_t Codec2Client::Component::configureVideoTunnel(
1313 uint32_t avSyncHwId,
1314 native_handle_t** sidebandHandle) {
1315 *sidebandHandle = nullptr;
1316 if (!mBase1_1) {
1317 return C2_OMITTED;
1318 }
1319 c2_status_t status{};
1320 Return<void> transStatus = mBase1_1->configureVideoTunnel(avSyncHwId,
1321 [&status, sidebandHandle](
1322 Status s, hardware::hidl_handle const& h) {
1323 status = static_cast<c2_status_t>(s);
1324 if (h.getNativeHandle()) {
1325 *sidebandHandle = native_handle_clone(h.getNativeHandle());
1326 }
1327 });
1328 if (!transStatus.isOk()) {
1329 LOG(ERROR) << "configureVideoTunnel -- transaction failed.";
1330 return C2_TRANSACTION_FAILED;
1331 }
1332 return status;
1333}
1334
Pawin Vongmasa36653902018-11-15 00:10:25 -08001335c2_status_t Codec2Client::Component::setOutputSurface(
1336 C2BlockPool::local_id_t blockPoolId,
1337 const sp<IGraphicBufferProducer>& surface,
1338 uint32_t generation) {
Sungtak Lee08515812019-06-05 11:16:32 -07001339 uint64_t bqId = 0;
1340 sp<IGraphicBufferProducer> nullIgbp;
1341 sp<HGraphicBufferProducer2> nullHgbp;
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08001342
Sungtak Lee08515812019-06-05 11:16:32 -07001343 sp<HGraphicBufferProducer2> igbp = surface ?
1344 surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
1345 if (surface && !igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001346 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001347 }
1348
Sungtak Lee08515812019-06-05 11:16:32 -07001349 if (!surface) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001350 mOutputBufferQueue->configure(nullIgbp, generation, 0);
Sungtak Lee08515812019-06-05 11:16:32 -07001351 } else if (surface->getUniqueId(&bqId) != OK) {
1352 LOG(ERROR) << "setOutputSurface -- "
1353 "cannot obtain bufferqueue id.";
1354 bqId = 0;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001355 mOutputBufferQueue->configure(nullIgbp, generation, 0);
Sungtak Lee08515812019-06-05 11:16:32 -07001356 } else {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001357 mOutputBufferQueue->configure(surface, generation, bqId);
Sungtak Lee08515812019-06-05 11:16:32 -07001358 }
1359 ALOGD("generation remote change %u", generation);
1360
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001361 Return<Status> transStatus = mBase1_0->setOutputSurface(
Sungtak Lee08515812019-06-05 11:16:32 -07001362 static_cast<uint64_t>(blockPoolId),
1363 bqId == 0 ? nullHgbp : igbp);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001364 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001365 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001366 return C2_TRANSACTION_FAILED;
1367 }
1368 c2_status_t status =
1369 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1370 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001371 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001372 }
1373 return status;
1374}
1375
1376status_t Codec2Client::Component::queueToOutputSurface(
1377 const C2ConstGraphicBlock& block,
1378 const QueueBufferInput& input,
1379 QueueBufferOutput* output) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001380 return mOutputBufferQueue->outputBuffer(block, input, output);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001381}
1382
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001383c2_status_t Codec2Client::Component::connectToInputSurface(
1384 const std::shared_ptr<InputSurface>& inputSurface,
1385 std::shared_ptr<InputSurfaceConnection>* connection) {
1386 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001387 Return<void> transStatus = mBase1_0->connectToInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001388 inputSurface->mBase,
1389 [&status, connection](
1390 Status s, const sp<IInputSurfaceConnection>& c) {
1391 status = static_cast<c2_status_t>(s);
1392 if (status != C2_OK) {
1393 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1394 << status << ".";
1395 return;
1396 }
1397 *connection = std::make_shared<InputSurfaceConnection>(c);
1398 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001399 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001400 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001401 return C2_TRANSACTION_FAILED;
1402 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001403 return status;
1404}
1405
1406c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001407 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001408 const sp<HGraphicBufferSource>& source,
1409 std::shared_ptr<InputSurfaceConnection>* connection) {
1410 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001411 Return<void> transStatus = mBase1_0->connectToOmxInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001412 producer, source,
1413 [&status, connection](
1414 Status s, const sp<IInputSurfaceConnection>& c) {
1415 status = static_cast<c2_status_t>(s);
1416 if (status != C2_OK) {
1417 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1418 << status << ".";
1419 return;
1420 }
1421 *connection = std::make_shared<InputSurfaceConnection>(c);
1422 });
1423 if (!transStatus.isOk()) {
1424 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1425 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001426 }
1427 return status;
1428}
1429
1430c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001431 Return<Status> transStatus = mBase1_0->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001432 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001433 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001434 return C2_TRANSACTION_FAILED;
1435 }
1436 c2_status_t status =
1437 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1438 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001439 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1440 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001441 }
1442 return status;
1443}
1444
1445c2_status_t Codec2Client::Component::setDeathListener(
1446 const std::shared_ptr<Component>& component,
1447 const std::shared_ptr<Listener>& listener) {
1448
1449 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1450 std::weak_ptr<Component> component;
1451 std::weak_ptr<Listener> base;
1452
1453 virtual void serviceDied(
1454 uint64_t /* cookie */,
1455 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1456 ) override {
1457 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1458 listener->onDeath(component);
1459 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001460 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001461 }
1462 }
1463 };
1464
1465 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1466 deathRecipient->base = listener;
1467 deathRecipient->component = component;
1468
1469 component->mDeathRecipient = deathRecipient;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001470 Return<bool> transResult = component->mBase1_0->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001471 component->mDeathRecipient, 0);
1472 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001473 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001474 return C2_TRANSACTION_FAILED;
1475 }
1476 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001477 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001478 return C2_CORRUPTED;
1479 }
1480 return C2_OK;
1481}
1482
1483// Codec2Client::InputSurface
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001484Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base)
1485 : Configurable{
1486 [base]() -> sp<IConfigurable> {
1487 Return<sp<IConfigurable>> transResult =
1488 base->getConfigurable();
1489 return transResult.isOk() ?
1490 static_cast<sp<IConfigurable>>(transResult) :
1491 nullptr;
1492 }()
1493 },
1494 mBase{base},
1495 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001496 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
1497 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001498 base->getGraphicBufferProducer();
1499 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001500 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001501 nullptr;
1502 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001503}
1504
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001505sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08001506 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1507 return mGraphicBufferProducer;
1508}
1509
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001510sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001511 return mBase;
1512}
1513
1514// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08001515Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001516 const sp<IInputSurfaceConnection>& base)
1517 : Configurable{
1518 [base]() -> sp<IConfigurable> {
1519 Return<sp<IConfigurable>> transResult =
1520 base->getConfigurable();
1521 return transResult.isOk() ?
1522 static_cast<sp<IConfigurable>>(transResult) :
1523 nullptr;
1524 }()
1525 },
1526 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001527}
1528
1529c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001530 Return<Status> transResult = mBase->disconnect();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001531 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1532}
1533
1534} // namespace android
1535