blob: bb02914575931cb508712fc2e899db8153dd90ba [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) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800618 if (status == C2_NOT_FOUND) {
619 LOG(VERBOSE) << "createComponent(" << name.c_str()
620 << ") -- component not found.";
621 } else {
622 LOG(ERROR) << "createComponent(" << name.c_str()
623 << ") -- call failed: " << status << ".";
624 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800625 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800626 } else if (!*component) {
627 LOG(ERROR) << "createComponent(" << name.c_str()
628 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800629 return C2_CORRUPTED;
630 }
631
632 status = (*component)->setDeathListener(*component, listener);
633 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800634 LOG(ERROR) << "createComponent(" << name.c_str()
635 << ") -- failed to set up death listener: "
636 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800637 }
638
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700639 (*component)->mBufferPoolSender->setReceiver(mHostPoolManager);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800640 return status;
641}
642
643c2_status_t Codec2Client::createInterface(
644 const C2String& name,
645 std::shared_ptr<Codec2Client::Interface>* const interface) {
646 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700647 Return<void> transStatus = mBase1_0->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800648 name,
649 [&status, interface](
650 Status s,
651 const sp<IComponentInterface>& i) {
652 status = static_cast<c2_status_t>(s);
653 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800654 return;
655 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800656 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800657 });
658 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800659 LOG(ERROR) << "createInterface(" << name.c_str()
660 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800661 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800662 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800663 if (status == C2_NOT_FOUND) {
664 LOG(VERBOSE) << "createInterface(" << name.c_str()
665 << ") -- component not found.";
666 } else {
667 LOG(ERROR) << "createInterface(" << name.c_str()
668 << ") -- call failed: " << status << ".";
669 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800670 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800671 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800672
Pawin Vongmasa36653902018-11-15 00:10:25 -0800673 return status;
674}
675
676c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800677 std::shared_ptr<InputSurface>* const inputSurface) {
678 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700679 Return<void> transStatus = mBase1_0->createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800680 [&status, inputSurface](
681 Status s,
682 const sp<IInputSurface>& i) {
683 status = static_cast<c2_status_t>(s);
684 if (status != C2_OK) {
685 return;
686 }
687 *inputSurface = std::make_shared<InputSurface>(i);
688 });
689 if (!transStatus.isOk()) {
690 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800691 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800692 } else if (status != C2_OK) {
693 LOG(DEBUG) << "createInputSurface -- call failed: "
694 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800695 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800696 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800697}
698
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700699std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
700 return Cache::List()[mServiceIndex].getTraits();
701}
702
703std::vector<C2Component::Traits> Codec2Client::_listComponents(
704 bool* success) const {
705 std::vector<C2Component::Traits> traits;
706 std::string const& serviceName = getServiceName();
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700707 Return<void> transStatus = mBase1_0->listComponents(
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700708 [&traits, &serviceName](Status s,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800709 const hidl_vec<IComponentStore::ComponentTraits>& t) {
710 if (s != Status::OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700711 LOG(DEBUG) << "_listComponents -- call failed: "
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800712 << static_cast<c2_status_t>(s) << ".";
713 return;
714 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700715 traits.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800716 for (size_t i = 0; i < t.size(); ++i) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700717 if (!objcpy(&traits[i], t[i])) {
718 LOG(ERROR) << "_listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800719 return;
720 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700721 traits[i].owner = serviceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800722 }
723 });
724 if (!transStatus.isOk()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700725 LOG(ERROR) << "_listComponents -- transaction failed.";
726 *success = false;
727 } else {
728 *success = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800729 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700730 return traits;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800731}
732
733c2_status_t Codec2Client::copyBuffer(
734 const std::shared_ptr<C2Buffer>& src,
735 const std::shared_ptr<C2Buffer>& dst) {
736 // TODO: Implement?
737 (void)src;
738 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800739 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800740 return C2_OMITTED;
741}
742
743std::shared_ptr<C2ParamReflector>
744 Codec2Client::getParamReflector() {
745 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
746 // should reflect the HAL API.
747 struct SimpleParamReflector : public C2ParamReflector {
748 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
749 hidl_vec<ParamIndex> indices(1);
750 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
751 std::unique_ptr<C2StructDescriptor> descriptor;
752 Return<void> transStatus = mBase->getStructDescriptors(
753 indices,
754 [&descriptor](
755 Status s,
756 const hidl_vec<StructDescriptor>& sd) {
757 c2_status_t status = static_cast<c2_status_t>(s);
758 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800759 LOG(DEBUG) << "SimpleParamReflector -- "
760 "getStructDescriptors() failed: "
761 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800762 descriptor.reset();
763 return;
764 }
765 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800766 LOG(DEBUG) << "SimpleParamReflector -- "
767 "getStructDescriptors() "
768 "returned vector of size "
769 << sd.size() << ". "
770 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800771 descriptor.reset();
772 return;
773 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800774 if (!objcpy(&descriptor, sd[0])) {
775 LOG(DEBUG) << "SimpleParamReflector -- "
776 "getStructDescriptors() returned "
777 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800778 descriptor.reset();
779 return;
780 }
781 });
782 return descriptor;
783 }
784
785 SimpleParamReflector(sp<Base> base)
786 : mBase(base) { }
787
788 sp<Base> mBase;
789 };
790
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700791 return std::make_shared<SimpleParamReflector>(mBase1_0);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800792};
793
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700794std::vector<std::string> const& Codec2Client::GetServiceNames() {
795 static std::vector<std::string> sServiceNames{[]() {
796 using ::android::hardware::media::c2::V1_0::IComponentStore;
797 using ::android::hidl::manager::V1_2::IServiceManager;
798
799 while (true) {
800 sp<IServiceManager> serviceManager = IServiceManager::getService();
801 CHECK(serviceManager) << "Hardware service manager is not running.";
802
803 // There are three categories of services based on names.
804 std::vector<std::string> defaultNames; // Prefixed with "default"
805 std::vector<std::string> vendorNames; // Prefixed with "vendor"
806 std::vector<std::string> otherNames; // Others
807 Return<void> transResult;
808 transResult = serviceManager->listManifestByInterface(
809 IComponentStore::descriptor,
810 [&defaultNames, &vendorNames, &otherNames](
811 hidl_vec<hidl_string> const& instanceNames) {
812 for (hidl_string const& instanceName : instanceNames) {
813 char const* name = instanceName.c_str();
814 if (strncmp(name, "default", 7) == 0) {
815 defaultNames.emplace_back(name);
816 } else if (strncmp(name, "vendor", 6) == 0) {
817 vendorNames.emplace_back(name);
818 } else {
819 otherNames.emplace_back(name);
820 }
821 }
822 });
823 if (transResult.isOk()) {
824 // Sort service names in each category.
825 std::sort(defaultNames.begin(), defaultNames.end());
826 std::sort(vendorNames.begin(), vendorNames.end());
827 std::sort(otherNames.begin(), otherNames.end());
828
829 // Concatenate the three lists in this order: default, vendor,
830 // other.
831 std::vector<std::string>& names = defaultNames;
832 names.reserve(names.size() + vendorNames.size() + otherNames.size());
833 names.insert(names.end(),
834 std::make_move_iterator(vendorNames.begin()),
835 std::make_move_iterator(vendorNames.end()));
836 names.insert(names.end(),
837 std::make_move_iterator(otherNames.begin()),
838 std::make_move_iterator(otherNames.end()));
839
840 // Summarize to logcat.
841 if (names.empty()) {
842 LOG(INFO) << "No Codec2 services declared in the manifest.";
843 } else {
844 std::stringstream stringOutput;
845 stringOutput << "Available Codec2 services:";
846 for (std::string const& name : names) {
847 stringOutput << " \"" << name << "\"";
848 }
849 LOG(INFO) << stringOutput.str();
850 }
851
852 return names;
853 }
854 LOG(ERROR) << "Could not retrieve the list of service instances of "
855 << IComponentStore::descriptor
856 << ". Retrying...";
857 }
858 }()};
859 return sServiceNames;
860}
861
Pawin Vongmasa36653902018-11-15 00:10:25 -0800862std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700863 const char* name) {
864 size_t index = getServiceIndex(name);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700865 return index == GetServiceNames().size() ?
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700866 nullptr : _CreateFromIndex(index);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800867}
868
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700869std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
870 CreateFromAllServices() {
871 std::vector<std::shared_ptr<Codec2Client>> clients(
872 GetServiceNames().size());
873 for (size_t i = GetServiceNames().size(); i > 0; ) {
874 --i;
875 clients[i] = _CreateFromIndex(i);
876 }
877 return clients;
878}
879
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700880std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700881 std::string const& name = GetServiceNames()[index];
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800882 LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700883 sp<Base> baseStore = Base::getService(name);
884 CHECK(baseStore) << "Codec2 service \"" << name << "\""
885 " inaccessible for unknown reasons.";
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800886 LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700887 return std::make_shared<Codec2Client>(baseStore, index);
888}
889
890c2_status_t Codec2Client::ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800891 const std::string &key,
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700892 size_t numberOfAttempts,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800893 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
894 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800895 c2_status_t status = C2_NO_INIT; // no IComponentStores present
896
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700897 // Cache the mapping key -> index of Codec2Client in Cache::List().
Pawin Vongmasa36653902018-11-15 00:10:25 -0800898 static std::mutex key2IndexMutex;
899 static std::map<std::string, size_t> key2Index;
900
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800901 // By default try all stores. However, try the last known client first. If
902 // the last known client fails, retry once. We do this by pushing the last
903 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800904 std::deque<size_t> indices;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700905 for (size_t index = Cache::List().size(); index > 0; ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800906 indices.push_front(--index);
907 }
908
909 bool wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700910 {
911 std::scoped_lock lock{key2IndexMutex};
912 auto it = key2Index.find(key);
913 if (it != key2Index.end()) {
914 indices.push_front(it->second);
915 wasMapped = true;
916 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800917 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800918
919 for (size_t index : indices) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700920 Cache& cache = Cache::List()[index];
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700921 for (size_t tries = numberOfAttempts; tries > 0; --tries) {
922 std::shared_ptr<Codec2Client> client{cache.getClient()};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800923 status = predicate(client);
924 if (status == C2_OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700925 std::scoped_lock lock{key2IndexMutex};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800926 key2Index[key] = index; // update last known client index
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700927 return C2_OK;
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700928 } else if (status == C2_TRANSACTION_FAILED) {
929 LOG(WARNING) << "\"" << key << "\" failed for service \""
930 << client->getName()
931 << "\" due to transaction failure. "
932 << "(Service may have crashed.)"
933 << (tries > 1 ? " Retrying..." : "");
934 cache.invalidate();
935 continue;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800936 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700937 if (wasMapped) {
938 LOG(INFO) << "\"" << key << "\" became invalid in service \""
939 << client->getName() << "\". Retrying...";
940 wasMapped = false;
941 }
942 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800943 }
944 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700945 return status; // return the last status from a valid client
Pawin Vongmasa36653902018-11-15 00:10:25 -0800946}
947
948std::shared_ptr<Codec2Client::Component>
949 Codec2Client::CreateComponentByName(
950 const char* componentName,
951 const std::shared_ptr<Listener>& listener,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -0700952 std::shared_ptr<Codec2Client>* owner,
953 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700954 std::string key{"create:"};
955 key.append(componentName);
956 std::shared_ptr<Component> component;
957 c2_status_t status = ForAllServices(
958 key,
959 numberOfAttempts,
960 [owner, &component, componentName, &listener](
961 const std::shared_ptr<Codec2Client> &client)
962 -> c2_status_t {
963 c2_status_t status = client->createComponent(componentName,
964 listener,
965 &component);
966 if (status == C2_OK) {
967 if (owner) {
968 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800969 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700970 } else if (status != C2_NOT_FOUND) {
971 LOG(DEBUG) << "IComponentStore("
972 << client->getServiceName()
973 << ")::createComponent(\"" << componentName
974 << "\") returned status = "
975 << status << ".";
976 }
977 return status;
978 });
979 if (status != C2_OK) {
980 LOG(DEBUG) << "Failed to create component \"" << componentName
981 << "\" from all known services. "
982 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800983 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700984 return component;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800985}
986
987std::shared_ptr<Codec2Client::Interface>
988 Codec2Client::CreateInterfaceByName(
989 const char* interfaceName,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -0700990 std::shared_ptr<Codec2Client>* owner,
991 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700992 std::string key{"create:"};
993 key.append(interfaceName);
994 std::shared_ptr<Interface> interface;
995 c2_status_t status = ForAllServices(
996 key,
997 numberOfAttempts,
998 [owner, &interface, interfaceName](
999 const std::shared_ptr<Codec2Client> &client)
1000 -> c2_status_t {
1001 c2_status_t status = client->createInterface(interfaceName,
1002 &interface);
1003 if (status == C2_OK) {
1004 if (owner) {
1005 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001006 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001007 } else if (status != C2_NOT_FOUND) {
1008 LOG(DEBUG) << "IComponentStore("
1009 << client->getServiceName()
1010 << ")::createInterface(\"" << interfaceName
1011 << "\") returned status = "
1012 << status << ".";
1013 }
1014 return status;
1015 });
1016 if (status != C2_OK) {
1017 LOG(DEBUG) << "Failed to create interface \"" << interfaceName
1018 << "\" from all known services. "
1019 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001020 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001021 return interface;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001022}
1023
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001024std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
1025 static std::vector<C2Component::Traits> sList{[]() {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001026 std::vector<C2Component::Traits> list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001027 for (Cache& cache : Cache::List()) {
1028 std::vector<C2Component::Traits> const& traits = cache.getTraits();
1029 list.insert(list.end(), traits.begin(), traits.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001030 }
1031 return list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001032 }()};
1033 return sList;
1034}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001035
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001036std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
1037 char const* serviceName) {
Pawin Vongmasa18588322019-05-18 01:52:13 -07001038 int32_t inputSurfaceSetting = ::android::base::GetIntProperty(
1039 "debug.stagefright.c2inputsurface", int32_t(0));
1040 if (inputSurfaceSetting <= 0) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001041 return nullptr;
1042 }
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001043 size_t index = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001044 if (serviceName) {
1045 index = getServiceIndex(serviceName);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001046 if (index == GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001047 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
1048 << serviceName << "\"";
1049 }
1050 }
1051
1052 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001053 if (index != GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001054 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
1055 if (client->createInputSurface(&inputSurface) == C2_OK) {
1056 return inputSurface;
1057 }
1058 }
1059 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
1060 "from all services...";
1061 for (Cache& cache : Cache::List()) {
1062 std::shared_ptr<Codec2Client> client = cache.getClient();
1063 if (client->createInputSurface(&inputSurface) == C2_OK) {
1064 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
1065 "service \"" << client->getServiceName() << "\"";
1066 return inputSurface;
1067 }
1068 }
1069 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
1070 "from all services";
1071 return nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001072}
1073
1074// Codec2Client::Listener
1075
1076Codec2Client::Listener::~Listener() {
1077}
1078
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001079// Codec2Client::Interface
1080Codec2Client::Interface::Interface(const sp<Base>& base)
1081 : Configurable{
1082 [base]() -> sp<IConfigurable> {
1083 Return<sp<IConfigurable>> transResult =
1084 base->getConfigurable();
1085 return transResult.isOk() ?
1086 static_cast<sp<IConfigurable>>(transResult) :
1087 nullptr;
1088 }()
1089 },
1090 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001091}
1092
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001093// Codec2Client::Component
1094Codec2Client::Component::Component(const sp<Base>& base)
1095 : Configurable{
1096 [base]() -> sp<IConfigurable> {
1097 Return<sp<IComponentInterface>> transResult1 =
1098 base->getInterface();
1099 if (!transResult1.isOk()) {
1100 return nullptr;
1101 }
1102 Return<sp<IConfigurable>> transResult2 =
1103 static_cast<sp<IComponentInterface>>(transResult1)->
1104 getConfigurable();
1105 return transResult2.isOk() ?
1106 static_cast<sp<IConfigurable>>(transResult2) :
1107 nullptr;
1108 }()
1109 },
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001110 mBase1_0{base},
1111 mBase1_1{Base1_1::castFrom(base)},
1112 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1113 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1114}
1115
1116Codec2Client::Component::Component(const sp<Base1_1>& base)
1117 : Configurable{
1118 [base]() -> sp<IConfigurable> {
1119 Return<sp<IComponentInterface>> transResult1 =
1120 base->getInterface();
1121 if (!transResult1.isOk()) {
1122 return nullptr;
1123 }
1124 Return<sp<IConfigurable>> transResult2 =
1125 static_cast<sp<IComponentInterface>>(transResult1)->
1126 getConfigurable();
1127 return transResult2.isOk() ?
1128 static_cast<sp<IConfigurable>>(transResult2) :
1129 nullptr;
1130 }()
1131 },
1132 mBase1_0{base},
1133 mBase1_1{base},
1134 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1135 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001136}
1137
1138Codec2Client::Component::~Component() {
1139}
1140
1141c2_status_t Codec2Client::Component::createBlockPool(
1142 C2Allocator::id_t id,
1143 C2BlockPool::local_id_t* blockPoolId,
1144 std::shared_ptr<Codec2Client::Configurable>* configurable) {
1145 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001146 Return<void> transStatus = mBase1_0->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001147 static_cast<uint32_t>(id),
1148 [&status, blockPoolId, configurable](
1149 Status s,
1150 uint64_t pId,
1151 const sp<IConfigurable>& c) {
1152 status = static_cast<c2_status_t>(s);
1153 configurable->reset();
1154 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001155 LOG(DEBUG) << "createBlockPool -- call failed: "
1156 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001157 return;
1158 }
1159 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001160 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001161 });
1162 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001163 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001164 return C2_TRANSACTION_FAILED;
1165 }
1166 return status;
1167}
1168
1169c2_status_t Codec2Client::Component::destroyBlockPool(
1170 C2BlockPool::local_id_t localId) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001171 Return<Status> transResult = mBase1_0->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001172 static_cast<uint64_t>(localId));
1173 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001174 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001175 return C2_TRANSACTION_FAILED;
1176 }
1177 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1178}
1179
Wonsik Kimab34ed62019-01-31 15:28:46 -08001180void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001181 const std::list<std::unique_ptr<C2Work>> &workItems) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001182 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001183 mOutputBufferQueue->holdBufferQueueBlocks(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001184}
1185
1186c2_status_t Codec2Client::Component::queue(
1187 std::list<std::unique_ptr<C2Work>>* const items) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001188 WorkBundle workBundle;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001189 if (!objcpy(&workBundle, *items, mBufferPoolSender.get())) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001190 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001191 return C2_TRANSACTION_FAILED;
1192 }
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001193 Return<Status> transStatus = mBase1_0->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001194 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001195 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001196 return C2_TRANSACTION_FAILED;
1197 }
1198 c2_status_t status =
1199 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1200 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001201 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001202 }
1203 return status;
1204}
1205
1206c2_status_t Codec2Client::Component::flush(
1207 C2Component::flush_mode_t mode,
1208 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
1209 (void)mode; // Flush mode isn't supported in HIDL yet.
1210 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001211 Return<void> transStatus = mBase1_0->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001212 [&status, flushedWork](
1213 Status s, const WorkBundle& wb) {
1214 status = static_cast<c2_status_t>(s);
1215 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001216 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001217 return;
1218 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001219 if (!objcpy(flushedWork, wb)) {
1220 status = C2_CORRUPTED;
1221 } else {
1222 status = C2_OK;
1223 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001224 });
1225 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001226 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001227 return C2_TRANSACTION_FAILED;
1228 }
1229
1230 // Indices of flushed work items.
1231 std::vector<uint64_t> flushedIndices;
1232 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
1233 if (work) {
1234 if (work->worklets.empty()
1235 || !work->worklets.back()
1236 || (work->worklets.back()->output.flags &
1237 C2FrameData::FLAG_INCOMPLETE) == 0) {
1238 // input is complete
1239 flushedIndices.emplace_back(
1240 work->input.ordinal.frameIndex.peeku());
1241 }
1242 }
1243 }
1244
Pawin Vongmasa36653902018-11-15 00:10:25 -08001245 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001246 mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001247
1248 return status;
1249}
1250
1251c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001252 Return<Status> transStatus = mBase1_0->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001253 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1254 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001255 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001256 return C2_TRANSACTION_FAILED;
1257 }
1258 c2_status_t status =
1259 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1260 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001261 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001262 }
1263 return status;
1264}
1265
1266c2_status_t Codec2Client::Component::start() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001267 Return<Status> transStatus = mBase1_0->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001268 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001269 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001270 return C2_TRANSACTION_FAILED;
1271 }
1272 c2_status_t status =
1273 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1274 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001275 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001276 }
1277 return status;
1278}
1279
1280c2_status_t Codec2Client::Component::stop() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001281 Return<Status> transStatus = mBase1_0->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001282 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001283 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001284 return C2_TRANSACTION_FAILED;
1285 }
1286 c2_status_t status =
1287 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1288 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001289 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001290 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001291 return status;
1292}
1293
1294c2_status_t Codec2Client::Component::reset() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001295 Return<Status> transStatus = mBase1_0->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001296 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001297 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001298 return C2_TRANSACTION_FAILED;
1299 }
1300 c2_status_t status =
1301 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1302 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001303 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001304 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001305 return status;
1306}
1307
1308c2_status_t Codec2Client::Component::release() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001309 Return<Status> transStatus = mBase1_0->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001310 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001311 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001312 return C2_TRANSACTION_FAILED;
1313 }
1314 c2_status_t status =
1315 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1316 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001317 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001318 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001319 return status;
1320}
1321
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001322c2_status_t Codec2Client::Component::configureVideoTunnel(
1323 uint32_t avSyncHwId,
1324 native_handle_t** sidebandHandle) {
1325 *sidebandHandle = nullptr;
1326 if (!mBase1_1) {
1327 return C2_OMITTED;
1328 }
1329 c2_status_t status{};
1330 Return<void> transStatus = mBase1_1->configureVideoTunnel(avSyncHwId,
1331 [&status, sidebandHandle](
1332 Status s, hardware::hidl_handle const& h) {
1333 status = static_cast<c2_status_t>(s);
1334 if (h.getNativeHandle()) {
1335 *sidebandHandle = native_handle_clone(h.getNativeHandle());
1336 }
1337 });
1338 if (!transStatus.isOk()) {
1339 LOG(ERROR) << "configureVideoTunnel -- transaction failed.";
1340 return C2_TRANSACTION_FAILED;
1341 }
1342 return status;
1343}
1344
Pawin Vongmasa36653902018-11-15 00:10:25 -08001345c2_status_t Codec2Client::Component::setOutputSurface(
1346 C2BlockPool::local_id_t blockPoolId,
1347 const sp<IGraphicBufferProducer>& surface,
1348 uint32_t generation) {
Sungtak Lee08515812019-06-05 11:16:32 -07001349 uint64_t bqId = 0;
1350 sp<IGraphicBufferProducer> nullIgbp;
1351 sp<HGraphicBufferProducer2> nullHgbp;
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08001352
Sungtak Lee08515812019-06-05 11:16:32 -07001353 sp<HGraphicBufferProducer2> igbp = surface ?
1354 surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
1355 if (surface && !igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001356 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001357 }
1358
Sungtak Lee08515812019-06-05 11:16:32 -07001359 if (!surface) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001360 mOutputBufferQueue->configure(nullIgbp, generation, 0);
Sungtak Lee08515812019-06-05 11:16:32 -07001361 } else if (surface->getUniqueId(&bqId) != OK) {
1362 LOG(ERROR) << "setOutputSurface -- "
1363 "cannot obtain bufferqueue id.";
1364 bqId = 0;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001365 mOutputBufferQueue->configure(nullIgbp, generation, 0);
Sungtak Lee08515812019-06-05 11:16:32 -07001366 } else {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001367 mOutputBufferQueue->configure(surface, generation, bqId);
Sungtak Lee08515812019-06-05 11:16:32 -07001368 }
1369 ALOGD("generation remote change %u", generation);
1370
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001371 Return<Status> transStatus = mBase1_0->setOutputSurface(
Sungtak Lee08515812019-06-05 11:16:32 -07001372 static_cast<uint64_t>(blockPoolId),
1373 bqId == 0 ? nullHgbp : igbp);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001374 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001375 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001376 return C2_TRANSACTION_FAILED;
1377 }
1378 c2_status_t status =
1379 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1380 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001381 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001382 }
1383 return status;
1384}
1385
1386status_t Codec2Client::Component::queueToOutputSurface(
1387 const C2ConstGraphicBlock& block,
1388 const QueueBufferInput& input,
1389 QueueBufferOutput* output) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001390 return mOutputBufferQueue->outputBuffer(block, input, output);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001391}
1392
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001393c2_status_t Codec2Client::Component::connectToInputSurface(
1394 const std::shared_ptr<InputSurface>& inputSurface,
1395 std::shared_ptr<InputSurfaceConnection>* connection) {
1396 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001397 Return<void> transStatus = mBase1_0->connectToInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001398 inputSurface->mBase,
1399 [&status, connection](
1400 Status s, const sp<IInputSurfaceConnection>& c) {
1401 status = static_cast<c2_status_t>(s);
1402 if (status != C2_OK) {
1403 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1404 << status << ".";
1405 return;
1406 }
1407 *connection = std::make_shared<InputSurfaceConnection>(c);
1408 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001409 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001410 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001411 return C2_TRANSACTION_FAILED;
1412 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001413 return status;
1414}
1415
1416c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001417 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001418 const sp<HGraphicBufferSource>& source,
1419 std::shared_ptr<InputSurfaceConnection>* connection) {
1420 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001421 Return<void> transStatus = mBase1_0->connectToOmxInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001422 producer, source,
1423 [&status, connection](
1424 Status s, const sp<IInputSurfaceConnection>& c) {
1425 status = static_cast<c2_status_t>(s);
1426 if (status != C2_OK) {
1427 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1428 << status << ".";
1429 return;
1430 }
1431 *connection = std::make_shared<InputSurfaceConnection>(c);
1432 });
1433 if (!transStatus.isOk()) {
1434 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1435 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001436 }
1437 return status;
1438}
1439
1440c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001441 Return<Status> transStatus = mBase1_0->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001442 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001443 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001444 return C2_TRANSACTION_FAILED;
1445 }
1446 c2_status_t status =
1447 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1448 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001449 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1450 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001451 }
1452 return status;
1453}
1454
1455c2_status_t Codec2Client::Component::setDeathListener(
1456 const std::shared_ptr<Component>& component,
1457 const std::shared_ptr<Listener>& listener) {
1458
1459 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1460 std::weak_ptr<Component> component;
1461 std::weak_ptr<Listener> base;
1462
1463 virtual void serviceDied(
1464 uint64_t /* cookie */,
1465 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1466 ) override {
1467 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1468 listener->onDeath(component);
1469 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001470 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001471 }
1472 }
1473 };
1474
1475 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1476 deathRecipient->base = listener;
1477 deathRecipient->component = component;
1478
1479 component->mDeathRecipient = deathRecipient;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001480 Return<bool> transResult = component->mBase1_0->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001481 component->mDeathRecipient, 0);
1482 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001483 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001484 return C2_TRANSACTION_FAILED;
1485 }
1486 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001487 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001488 return C2_CORRUPTED;
1489 }
1490 return C2_OK;
1491}
1492
1493// Codec2Client::InputSurface
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001494Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base)
1495 : Configurable{
1496 [base]() -> sp<IConfigurable> {
1497 Return<sp<IConfigurable>> transResult =
1498 base->getConfigurable();
1499 return transResult.isOk() ?
1500 static_cast<sp<IConfigurable>>(transResult) :
1501 nullptr;
1502 }()
1503 },
1504 mBase{base},
1505 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001506 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
1507 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001508 base->getGraphicBufferProducer();
1509 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001510 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001511 nullptr;
1512 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001513}
1514
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001515sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08001516 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1517 return mGraphicBufferProducer;
1518}
1519
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001520sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001521 return mBase;
1522}
1523
1524// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08001525Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001526 const sp<IInputSurfaceConnection>& base)
1527 : Configurable{
1528 [base]() -> sp<IConfigurable> {
1529 Return<sp<IConfigurable>> transResult =
1530 base->getConfigurable();
1531 return transResult.isOk() ?
1532 static_cast<sp<IConfigurable>>(transResult) :
1533 nullptr;
1534 }()
1535 },
1536 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001537}
1538
1539c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001540 Return<Status> transResult = mBase->disconnect();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001541 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1542}
1543
1544} // namespace android
1545