blob: 341a57718822c1033113b910c2c372d764f9fd99 [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 Vongmasa83d2c552020-03-05 04:36:08 -080096class Client2Store : public C2ComponentStore {
97 std::shared_ptr<Codec2Client> mClient;
98
99public:
100 Client2Store(std::shared_ptr<Codec2Client> const& client)
101 : mClient(client) { }
102
103 virtual ~Client2Store() = default;
104
105 virtual c2_status_t config_sm(
106 std::vector<C2Param*> const &params,
107 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
108 return mClient->config(params, C2_MAY_BLOCK, failures);
109 };
110
111 virtual c2_status_t copyBuffer(
112 std::shared_ptr<C2GraphicBuffer>,
113 std::shared_ptr<C2GraphicBuffer>) {
114 return C2_OMITTED;
115 }
116
117 virtual c2_status_t createComponent(
118 C2String, std::shared_ptr<C2Component>* const component) {
119 component->reset();
120 return C2_OMITTED;
121 }
122
123 virtual c2_status_t createInterface(
124 C2String, std::shared_ptr<C2ComponentInterface>* const interface) {
125 interface->reset();
126 return C2_OMITTED;
127 }
128
129 virtual c2_status_t query_sm(
130 std::vector<C2Param*> const& stackParams,
131 std::vector<C2Param::Index> const& heapParamIndices,
132 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
133 return mClient->query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
134 }
135
136 virtual c2_status_t querySupportedParams_nb(
137 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
138 return mClient->querySupportedParams(params);
139 }
140
141 virtual c2_status_t querySupportedValues_sm(
142 std::vector<C2FieldSupportedValuesQuery>& fields) const {
143 return mClient->querySupportedValues(fields, C2_MAY_BLOCK);
144 }
145
146 virtual C2String getName() const {
147 return mClient->getName();
148 }
149
150 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const {
151 return mClient->getParamReflector();
152 }
153
154 virtual std::vector<std::shared_ptr<C2Component::Traits const>> listComponents() {
155 return std::vector<std::shared_ptr<C2Component::Traits const>>();
156 }
157};
158
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700159} // unnamed namespace
160
161// This class caches a Codec2Client object and its component traits. The client
162// will be created the first time it is needed, and it can be refreshed if the
163// service dies (by calling invalidate()). The first time listComponents() is
164// called from the client, the result will be cached.
165class Codec2Client::Cache {
166 // Cached client
167 std::shared_ptr<Codec2Client> mClient;
168 mutable std::mutex mClientMutex;
169
170 // Cached component traits
171 std::vector<C2Component::Traits> mTraits;
172 std::once_flag mTraitsInitializationFlag;
173
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700174 // The index of the service. This is based on GetServiceNames().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700175 size_t mIndex;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700176 // Called by s() exactly once to initialize the cache. The index must be a
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700177 // valid index into the vector returned by GetServiceNames(). Calling
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700178 // init(index) will associate the cache to the service with name
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700179 // GetServiceNames()[index].
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700180 void init(size_t index) {
181 mIndex = index;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700182 }
183
184public:
185 Cache() = default;
186
187 // Initializes mClient if needed, then returns mClient.
188 // If the service is unavailable but listed in the manifest, this function
189 // will block indefinitely.
190 std::shared_ptr<Codec2Client> getClient() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700191 std::scoped_lock lock{mClientMutex};
192 if (!mClient) {
193 mClient = Codec2Client::_CreateFromIndex(mIndex);
194 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700195 CHECK(mClient) << "Failed to create Codec2Client to service \""
196 << GetServiceNames()[mIndex] << "\". (Index = "
197 << mIndex << ").";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700198 return mClient;
199 }
200
201 // Causes a subsequent call to getClient() to create a new client. This
202 // function should be called after the service dies.
203 //
204 // Note: This function is called only by ForAllServices().
205 void invalidate() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700206 std::scoped_lock lock{mClientMutex};
207 mClient = nullptr;
208 }
209
210 // Returns a list of traits for components supported by the service. This
211 // list is cached.
212 std::vector<C2Component::Traits> const& getTraits() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700213 std::call_once(mTraitsInitializationFlag, [this]() {
214 bool success{false};
215 // Spin until _listComponents() is successful.
216 while (true) {
217 std::shared_ptr<Codec2Client> client = getClient();
218 mTraits = client->_listComponents(&success);
219 if (success) {
220 break;
221 }
Pawin Vongmasa21617db2020-04-24 06:16:42 -0700222 invalidate();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700223 using namespace std::chrono_literals;
224 static constexpr auto kServiceRetryPeriod = 5s;
225 LOG(INFO) << "Failed to retrieve component traits from service "
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700226 "\"" << GetServiceNames()[mIndex] << "\". "
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700227 "Retrying...";
228 std::this_thread::sleep_for(kServiceRetryPeriod);
229 }
230 });
231 return mTraits;
232 }
233
234 // List() returns the list of all caches.
235 static std::vector<Cache>& List() {
236 static std::vector<Cache> sCaches{[]() {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700237 size_t numServices = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700238 std::vector<Cache> caches(numServices);
239 for (size_t i = 0; i < numServices; ++i) {
240 caches[i].init(i);
241 }
242 return caches;
243 }()};
244 return sCaches;
245 }
246};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800247
248// Codec2ConfigurableClient
249
250const C2String& Codec2ConfigurableClient::getName() const {
251 return mName;
252}
253
Pawin Vongmasa36653902018-11-15 00:10:25 -0800254Codec2ConfigurableClient::Codec2ConfigurableClient(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800255 const sp<IConfigurable>& base)
256 : mBase{base},
257 mName{[base]() -> C2String {
258 C2String outName;
259 Return<void> transStatus = base->getName(
260 [&outName](const hidl_string& name) {
261 outName = name.c_str();
262 });
263 return transStatus.isOk() ? outName : "";
264 }()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800265}
266
267c2_status_t Codec2ConfigurableClient::query(
268 const std::vector<C2Param*> &stackParams,
269 const std::vector<C2Param::Index> &heapParamIndices,
270 c2_blocking_t mayBlock,
271 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
272 hidl_vec<ParamIndex> indices(
273 stackParams.size() + heapParamIndices.size());
274 size_t numIndices = 0;
275 for (C2Param* const& stackParam : stackParams) {
276 if (!stackParam) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800277 LOG(WARNING) << "query -- null stack param encountered.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800278 continue;
279 }
280 indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
281 }
282 size_t numStackIndices = numIndices;
283 for (const C2Param::Index& index : heapParamIndices) {
284 indices[numIndices++] =
285 static_cast<ParamIndex>(static_cast<uint32_t>(index));
286 }
287 indices.resize(numIndices);
288 if (heapParams) {
289 heapParams->reserve(heapParams->size() + numIndices);
290 }
291 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800292 Return<void> transStatus = mBase->query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800293 indices,
294 mayBlock == C2_MAY_BLOCK,
295 [&status, &numStackIndices, &stackParams, heapParams](
296 Status s, const Params& p) {
297 status = static_cast<c2_status_t>(s);
298 if (status != C2_OK && status != C2_BAD_INDEX) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800299 LOG(DEBUG) << "query -- call failed: "
300 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800301 return;
302 }
303 std::vector<C2Param*> paramPointers;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800304 if (!parseParamsBlob(&paramPointers, p)) {
305 LOG(ERROR) << "query -- error while parsing params.";
306 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800307 return;
308 }
309 size_t i = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800310 for (auto it = paramPointers.begin();
311 it != paramPointers.end(); ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800312 C2Param* paramPointer = *it;
313 if (numStackIndices > 0) {
314 --numStackIndices;
315 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800316 LOG(WARNING) << "query -- null stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800317 ++it;
318 continue;
319 }
320 for (; i < stackParams.size() && !stackParams[i]; ) {
321 ++i;
322 }
323 if (i >= stackParams.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800324 LOG(ERROR) << "query -- unexpected error.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800325 status = C2_CORRUPTED;
326 return;
327 }
328 if (stackParams[i]->index() != paramPointer->index()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800329 LOG(WARNING) << "query -- param skipped: "
330 "index = "
331 << stackParams[i]->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800332 stackParams[i++]->invalidate();
333 continue;
334 }
335 if (!stackParams[i++]->updateFrom(*paramPointer)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800336 LOG(WARNING) << "query -- param update failed: "
337 "index = "
338 << paramPointer->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800339 }
340 } else {
341 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800342 LOG(WARNING) << "query -- null heap param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800343 ++it;
344 continue;
345 }
346 if (!heapParams) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800347 LOG(WARNING) << "query -- "
348 "unexpected extra stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800349 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800350 heapParams->emplace_back(
351 C2Param::Copy(*paramPointer));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800352 }
353 }
354 ++it;
355 }
356 });
357 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800358 LOG(ERROR) << "query -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800359 return C2_TRANSACTION_FAILED;
360 }
361 return status;
362}
363
364c2_status_t Codec2ConfigurableClient::config(
365 const std::vector<C2Param*> &params,
366 c2_blocking_t mayBlock,
367 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
368 Params hidlParams;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800369 if (!createParamsBlob(&hidlParams, params)) {
370 LOG(ERROR) << "config -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800371 return C2_TRANSACTION_FAILED;
372 }
373 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800374 Return<void> transStatus = mBase->config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800375 hidlParams,
376 mayBlock == C2_MAY_BLOCK,
377 [&status, &params, failures](
378 Status s,
379 const hidl_vec<SettingResult> f,
380 const Params& o) {
381 status = static_cast<c2_status_t>(s);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800382 if (status != C2_OK && status != C2_BAD_INDEX) {
383 LOG(DEBUG) << "config -- call failed: "
384 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800385 }
386 size_t i = failures->size();
387 failures->resize(i + f.size());
388 for (const SettingResult& sf : f) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800389 if (!objcpy(&(*failures)[i++], sf)) {
390 LOG(ERROR) << "config -- "
391 << "invalid SettingResult returned.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800392 return;
393 }
394 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800395 if (!updateParamsFromBlob(params, o)) {
396 LOG(ERROR) << "config -- "
397 << "failed to parse returned params.";
398 status = C2_CORRUPTED;
399 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800400 });
401 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800402 LOG(ERROR) << "config -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800403 return C2_TRANSACTION_FAILED;
404 }
405 return status;
406}
407
408c2_status_t Codec2ConfigurableClient::querySupportedParams(
409 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
410 // TODO: Cache and query properly!
411 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800412 Return<void> transStatus = mBase->querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800413 std::numeric_limits<uint32_t>::min(),
414 std::numeric_limits<uint32_t>::max(),
415 [&status, params](
416 Status s,
417 const hidl_vec<ParamDescriptor>& p) {
418 status = static_cast<c2_status_t>(s);
419 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800420 LOG(DEBUG) << "querySupportedParams -- call failed: "
421 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800422 return;
423 }
424 size_t i = params->size();
425 params->resize(i + p.size());
426 for (const ParamDescriptor& sp : p) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800427 if (!objcpy(&(*params)[i++], sp)) {
428 LOG(ERROR) << "querySupportedParams -- "
429 << "invalid returned ParamDescriptor.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800430 return;
431 }
432 }
433 });
434 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800435 LOG(ERROR) << "querySupportedParams -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800436 return C2_TRANSACTION_FAILED;
437 }
438 return status;
439}
440
441c2_status_t Codec2ConfigurableClient::querySupportedValues(
442 std::vector<C2FieldSupportedValuesQuery>& fields,
443 c2_blocking_t mayBlock) const {
444 hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
445 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800446 if (!objcpy(&inFields[i], fields[i])) {
447 LOG(ERROR) << "querySupportedValues -- bad input";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800448 return C2_TRANSACTION_FAILED;
449 }
450 }
451
452 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800453 Return<void> transStatus = mBase->querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800454 inFields,
455 mayBlock == C2_MAY_BLOCK,
456 [&status, &inFields, &fields](
457 Status s,
458 const hidl_vec<FieldSupportedValuesQueryResult>& r) {
459 status = static_cast<c2_status_t>(s);
460 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800461 LOG(DEBUG) << "querySupportedValues -- call failed: "
462 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800463 return;
464 }
465 if (r.size() != fields.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800466 LOG(ERROR) << "querySupportedValues -- "
467 "input and output lists "
468 "have different sizes.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800469 status = C2_CORRUPTED;
470 return;
471 }
472 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800473 if (!objcpy(&fields[i], inFields[i], r[i])) {
474 LOG(ERROR) << "querySupportedValues -- "
475 "invalid returned value.";
476 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800477 return;
478 }
479 }
480 });
481 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800482 LOG(ERROR) << "querySupportedValues -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800483 return C2_TRANSACTION_FAILED;
484 }
485 return status;
486}
487
488// Codec2Client::Component::HidlListener
489struct Codec2Client::Component::HidlListener : public IComponentListener {
490 std::weak_ptr<Component> component;
491 std::weak_ptr<Listener> base;
492
493 virtual Return<void> onWorkDone(const WorkBundle& workBundle) override {
494 std::list<std::unique_ptr<C2Work>> workItems;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800495 if (!objcpy(&workItems, workBundle)) {
496 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800497 return Void();
498 }
499 // release input buffers potentially held by the component from queue
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800500 std::shared_ptr<Codec2Client::Component> strongComponent =
501 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800502 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800503 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800504 }
505 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800506 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800507 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800508 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800509 }
510 return Void();
511 }
512
513 virtual Return<void> onTripped(
514 const hidl_vec<SettingResult>& settingResults) override {
515 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
516 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800517 for (size_t i = 0; i < settingResults.size(); ++i) {
518 std::unique_ptr<C2SettingResult> c2SettingResult;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800519 if (!objcpy(&c2SettingResult, settingResults[i])) {
520 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800521 return Void();
522 }
523 c2SettingResults[i] = std::move(c2SettingResult);
524 }
525 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
526 listener->onTripped(component, c2SettingResults);
527 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800528 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800529 }
530 return Void();
531 }
532
533 virtual Return<void> onError(Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800534 LOG(DEBUG) << "onError --"
535 << " status = " << s
536 << ", errorCode = " << errorCode
537 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800538 if (std::shared_ptr<Listener> listener = base.lock()) {
539 listener->onError(component, s == Status::OK ?
540 errorCode : static_cast<c2_status_t>(s));
541 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800542 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800543 }
544 return Void();
545 }
546
547 virtual Return<void> onFramesRendered(
548 const hidl_vec<RenderedFrame>& renderedFrames) override {
549 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800550 if (!listener) {
551 LOG(DEBUG) << "onFramesRendered -- listener died.";
552 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800553 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800554 for (const RenderedFrame& renderedFrame : renderedFrames) {
555 listener->onFrameRendered(
556 renderedFrame.bufferQueueId,
557 renderedFrame.slotId,
558 renderedFrame.timestampNs);
559 }
560 return Void();
561 }
562
563 virtual Return<void> onInputBuffersReleased(
564 const hidl_vec<InputBuffer>& inputBuffers) override {
565 std::shared_ptr<Listener> listener = base.lock();
566 if (!listener) {
567 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
568 return Void();
569 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800570 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800571 LOG(VERBOSE) << "onInputBuffersReleased --"
572 " received death notification of"
573 " input buffer:"
574 " frameIndex = " << inputBuffer.frameIndex
575 << ", bufferIndex = " << inputBuffer.arrayIndex
576 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -0800577 listener->onInputBufferDone(
578 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800579 }
580 return Void();
581 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800582
Pawin Vongmasa36653902018-11-15 00:10:25 -0800583};
584
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700585// Codec2Client::Component::BufferPoolSender
586struct Codec2Client::Component::BufferPoolSender :
587 hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
588 BufferPoolSender()
589 : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
590 }
591};
592
593// Codec2Client::Component::OutputBufferQueue
594struct Codec2Client::Component::OutputBufferQueue :
595 hardware::media::c2::V1_1::utils::OutputBufferQueue {
596 OutputBufferQueue()
597 : hardware::media::c2::V1_1::utils::OutputBufferQueue() {
598 }
599};
600
Pawin Vongmasa36653902018-11-15 00:10:25 -0800601// Codec2Client
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700602Codec2Client::Codec2Client(sp<Base> const& base,
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700603 size_t serviceIndex)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800604 : Configurable{
605 [base]() -> sp<IConfigurable> {
606 Return<sp<IConfigurable>> transResult =
607 base->getConfigurable();
608 return transResult.isOk() ?
609 static_cast<sp<IConfigurable>>(transResult) :
610 nullptr;
611 }()
612 },
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700613 mBase1_0{base},
614 mBase1_1{Base1_1::castFrom(base)},
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700615 mServiceIndex{serviceIndex} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800616 Return<sp<IClientManager>> transResult = base->getPoolClientManager();
617 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800618 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800619 } else {
620 mHostPoolManager = static_cast<sp<IClientManager>>(transResult);
621 }
622}
623
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700624sp<Codec2Client::Base> const& Codec2Client::getBase() const {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700625 return mBase1_0;
626}
627
628sp<Codec2Client::Base1_0> const& Codec2Client::getBase1_0() const {
629 return mBase1_0;
630}
631
632sp<Codec2Client::Base1_1> const& Codec2Client::getBase1_1() const {
633 return mBase1_1;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700634}
635
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700636std::string const& Codec2Client::getServiceName() const {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700637 return GetServiceNames()[mServiceIndex];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700638}
639
Pawin Vongmasa36653902018-11-15 00:10:25 -0800640c2_status_t Codec2Client::createComponent(
641 const C2String& name,
642 const std::shared_ptr<Codec2Client::Listener>& listener,
643 std::shared_ptr<Codec2Client::Component>* const component) {
644
Pawin Vongmasa36653902018-11-15 00:10:25 -0800645 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800646 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800647 hidlListener->base = listener;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700648 Return<void> transStatus = mBase1_1 ?
649 mBase1_1->createComponent_1_1(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800650 name,
651 hidlListener,
652 ClientManager::getInstance(),
653 [&status, component, hidlListener](
654 Status s,
655 const sp<IComponent>& c) {
656 status = static_cast<c2_status_t>(s);
657 if (status != C2_OK) {
658 return;
659 }
660 *component = std::make_shared<Codec2Client::Component>(c);
661 hidlListener->component = *component;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700662 }) :
663 mBase1_0->createComponent(
664 name,
665 hidlListener,
666 ClientManager::getInstance(),
667 [&status, component, hidlListener](
668 Status s,
669 const sp<hardware::media::c2::V1_0::IComponent>& c) {
670 status = static_cast<c2_status_t>(s);
671 if (status != C2_OK) {
672 return;
673 }
674 *component = std::make_shared<Codec2Client::Component>(c);
675 hidlListener->component = *component;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800676 });
677 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800678 LOG(ERROR) << "createComponent(" << name.c_str()
679 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800680 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800681 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800682 if (status == C2_NOT_FOUND) {
683 LOG(VERBOSE) << "createComponent(" << name.c_str()
684 << ") -- component not found.";
685 } else {
686 LOG(ERROR) << "createComponent(" << name.c_str()
687 << ") -- call failed: " << status << ".";
688 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800689 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800690 } else if (!*component) {
691 LOG(ERROR) << "createComponent(" << name.c_str()
692 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800693 return C2_CORRUPTED;
694 }
695
696 status = (*component)->setDeathListener(*component, listener);
697 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800698 LOG(ERROR) << "createComponent(" << name.c_str()
699 << ") -- failed to set up death listener: "
700 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800701 }
702
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700703 (*component)->mBufferPoolSender->setReceiver(mHostPoolManager);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800704 return status;
705}
706
707c2_status_t Codec2Client::createInterface(
708 const C2String& name,
709 std::shared_ptr<Codec2Client::Interface>* const interface) {
710 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700711 Return<void> transStatus = mBase1_0->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800712 name,
713 [&status, interface](
714 Status s,
715 const sp<IComponentInterface>& i) {
716 status = static_cast<c2_status_t>(s);
717 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800718 return;
719 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800720 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800721 });
722 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800723 LOG(ERROR) << "createInterface(" << name.c_str()
724 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800725 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800726 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800727 if (status == C2_NOT_FOUND) {
728 LOG(VERBOSE) << "createInterface(" << name.c_str()
729 << ") -- component not found.";
730 } else {
731 LOG(ERROR) << "createInterface(" << name.c_str()
732 << ") -- call failed: " << status << ".";
733 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800734 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800735 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800736
Pawin Vongmasa36653902018-11-15 00:10:25 -0800737 return status;
738}
739
740c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800741 std::shared_ptr<InputSurface>* const inputSurface) {
742 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700743 Return<void> transStatus = mBase1_0->createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800744 [&status, inputSurface](
745 Status s,
746 const sp<IInputSurface>& i) {
747 status = static_cast<c2_status_t>(s);
748 if (status != C2_OK) {
749 return;
750 }
751 *inputSurface = std::make_shared<InputSurface>(i);
752 });
753 if (!transStatus.isOk()) {
754 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800755 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800756 } else if (status != C2_OK) {
757 LOG(DEBUG) << "createInputSurface -- call failed: "
758 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800759 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800760 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800761}
762
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700763std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
764 return Cache::List()[mServiceIndex].getTraits();
765}
766
767std::vector<C2Component::Traits> Codec2Client::_listComponents(
768 bool* success) const {
769 std::vector<C2Component::Traits> traits;
770 std::string const& serviceName = getServiceName();
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700771 Return<void> transStatus = mBase1_0->listComponents(
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700772 [&traits, &serviceName](Status s,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800773 const hidl_vec<IComponentStore::ComponentTraits>& t) {
774 if (s != Status::OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700775 LOG(DEBUG) << "_listComponents -- call failed: "
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800776 << static_cast<c2_status_t>(s) << ".";
777 return;
778 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700779 traits.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800780 for (size_t i = 0; i < t.size(); ++i) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700781 if (!objcpy(&traits[i], t[i])) {
782 LOG(ERROR) << "_listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800783 return;
784 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700785 traits[i].owner = serviceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800786 }
787 });
788 if (!transStatus.isOk()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700789 LOG(ERROR) << "_listComponents -- transaction failed.";
790 *success = false;
791 } else {
792 *success = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800793 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700794 return traits;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800795}
796
797c2_status_t Codec2Client::copyBuffer(
798 const std::shared_ptr<C2Buffer>& src,
799 const std::shared_ptr<C2Buffer>& dst) {
800 // TODO: Implement?
801 (void)src;
802 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800803 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800804 return C2_OMITTED;
805}
806
807std::shared_ptr<C2ParamReflector>
808 Codec2Client::getParamReflector() {
809 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
810 // should reflect the HAL API.
811 struct SimpleParamReflector : public C2ParamReflector {
812 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
813 hidl_vec<ParamIndex> indices(1);
814 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
815 std::unique_ptr<C2StructDescriptor> descriptor;
816 Return<void> transStatus = mBase->getStructDescriptors(
817 indices,
818 [&descriptor](
819 Status s,
820 const hidl_vec<StructDescriptor>& sd) {
821 c2_status_t status = static_cast<c2_status_t>(s);
822 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800823 LOG(DEBUG) << "SimpleParamReflector -- "
824 "getStructDescriptors() failed: "
825 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800826 descriptor.reset();
827 return;
828 }
829 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800830 LOG(DEBUG) << "SimpleParamReflector -- "
831 "getStructDescriptors() "
832 "returned vector of size "
833 << sd.size() << ". "
834 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800835 descriptor.reset();
836 return;
837 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800838 if (!objcpy(&descriptor, sd[0])) {
839 LOG(DEBUG) << "SimpleParamReflector -- "
840 "getStructDescriptors() returned "
841 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800842 descriptor.reset();
843 return;
844 }
845 });
Wonsik Kim492fecd2020-11-19 11:14:11 -0800846 if (!transStatus.isOk()) {
847 LOG(DEBUG) << "SimpleParamReflector -- transaction failed: "
848 << transStatus.description();
849 descriptor.reset();
850 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800851 return descriptor;
852 }
853
854 SimpleParamReflector(sp<Base> base)
855 : mBase(base) { }
856
857 sp<Base> mBase;
858 };
859
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700860 return std::make_shared<SimpleParamReflector>(mBase1_0);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800861};
862
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700863std::vector<std::string> const& Codec2Client::GetServiceNames() {
864 static std::vector<std::string> sServiceNames{[]() {
865 using ::android::hardware::media::c2::V1_0::IComponentStore;
866 using ::android::hidl::manager::V1_2::IServiceManager;
867
868 while (true) {
869 sp<IServiceManager> serviceManager = IServiceManager::getService();
870 CHECK(serviceManager) << "Hardware service manager is not running.";
871
872 // There are three categories of services based on names.
873 std::vector<std::string> defaultNames; // Prefixed with "default"
874 std::vector<std::string> vendorNames; // Prefixed with "vendor"
875 std::vector<std::string> otherNames; // Others
876 Return<void> transResult;
877 transResult = serviceManager->listManifestByInterface(
878 IComponentStore::descriptor,
879 [&defaultNames, &vendorNames, &otherNames](
880 hidl_vec<hidl_string> const& instanceNames) {
881 for (hidl_string const& instanceName : instanceNames) {
882 char const* name = instanceName.c_str();
883 if (strncmp(name, "default", 7) == 0) {
884 defaultNames.emplace_back(name);
885 } else if (strncmp(name, "vendor", 6) == 0) {
886 vendorNames.emplace_back(name);
887 } else {
888 otherNames.emplace_back(name);
889 }
890 }
891 });
892 if (transResult.isOk()) {
893 // Sort service names in each category.
894 std::sort(defaultNames.begin(), defaultNames.end());
895 std::sort(vendorNames.begin(), vendorNames.end());
896 std::sort(otherNames.begin(), otherNames.end());
897
898 // Concatenate the three lists in this order: default, vendor,
899 // other.
900 std::vector<std::string>& names = defaultNames;
901 names.reserve(names.size() + vendorNames.size() + otherNames.size());
902 names.insert(names.end(),
903 std::make_move_iterator(vendorNames.begin()),
904 std::make_move_iterator(vendorNames.end()));
905 names.insert(names.end(),
906 std::make_move_iterator(otherNames.begin()),
907 std::make_move_iterator(otherNames.end()));
908
909 // Summarize to logcat.
910 if (names.empty()) {
911 LOG(INFO) << "No Codec2 services declared in the manifest.";
912 } else {
913 std::stringstream stringOutput;
914 stringOutput << "Available Codec2 services:";
915 for (std::string const& name : names) {
916 stringOutput << " \"" << name << "\"";
917 }
918 LOG(INFO) << stringOutput.str();
919 }
920
921 return names;
922 }
923 LOG(ERROR) << "Could not retrieve the list of service instances of "
924 << IComponentStore::descriptor
925 << ". Retrying...";
926 }
927 }()};
928 return sServiceNames;
929}
930
Pawin Vongmasa36653902018-11-15 00:10:25 -0800931std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa83d2c552020-03-05 04:36:08 -0800932 const char* name,
933 bool setAsPreferredCodec2ComponentStore) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700934 size_t index = getServiceIndex(name);
Pawin Vongmasa83d2c552020-03-05 04:36:08 -0800935 if (index == GetServiceNames().size()) {
936 if (setAsPreferredCodec2ComponentStore) {
937 LOG(WARNING) << "CreateFromService(" << name
938 << ") -- preferred C2ComponentStore not set.";
939 }
940 return nullptr;
941 }
942 std::shared_ptr<Codec2Client> client = _CreateFromIndex(index);
943 if (setAsPreferredCodec2ComponentStore) {
944 SetPreferredCodec2ComponentStore(
945 std::make_shared<Client2Store>(client));
946 LOG(INFO) << "CreateFromService(" << name
947 << ") -- service set as preferred C2ComponentStore.";
948 }
949 return client;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800950}
951
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700952std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
953 CreateFromAllServices() {
954 std::vector<std::shared_ptr<Codec2Client>> clients(
955 GetServiceNames().size());
956 for (size_t i = GetServiceNames().size(); i > 0; ) {
957 --i;
958 clients[i] = _CreateFromIndex(i);
959 }
960 return clients;
961}
962
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700963std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700964 std::string const& name = GetServiceNames()[index];
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800965 LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700966 sp<Base> baseStore = Base::getService(name);
967 CHECK(baseStore) << "Codec2 service \"" << name << "\""
968 " inaccessible for unknown reasons.";
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800969 LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700970 return std::make_shared<Codec2Client>(baseStore, index);
971}
972
973c2_status_t Codec2Client::ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800974 const std::string &key,
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700975 size_t numberOfAttempts,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800976 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
977 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800978 c2_status_t status = C2_NO_INIT; // no IComponentStores present
979
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700980 // Cache the mapping key -> index of Codec2Client in Cache::List().
Pawin Vongmasa36653902018-11-15 00:10:25 -0800981 static std::mutex key2IndexMutex;
982 static std::map<std::string, size_t> key2Index;
983
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800984 // By default try all stores. However, try the last known client first. If
985 // the last known client fails, retry once. We do this by pushing the last
986 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800987 std::deque<size_t> indices;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700988 for (size_t index = Cache::List().size(); index > 0; ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800989 indices.push_front(--index);
990 }
991
992 bool wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700993 {
994 std::scoped_lock lock{key2IndexMutex};
995 auto it = key2Index.find(key);
996 if (it != key2Index.end()) {
997 indices.push_front(it->second);
998 wasMapped = true;
999 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001000 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001001
1002 for (size_t index : indices) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001003 Cache& cache = Cache::List()[index];
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001004 for (size_t tries = numberOfAttempts; tries > 0; --tries) {
1005 std::shared_ptr<Codec2Client> client{cache.getClient()};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001006 status = predicate(client);
1007 if (status == C2_OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001008 std::scoped_lock lock{key2IndexMutex};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001009 key2Index[key] = index; // update last known client index
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001010 return C2_OK;
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001011 } else if (status == C2_NO_MEMORY) {
1012 return C2_NO_MEMORY;
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001013 } else if (status == C2_TRANSACTION_FAILED) {
1014 LOG(WARNING) << "\"" << key << "\" failed for service \""
1015 << client->getName()
1016 << "\" due to transaction failure. "
1017 << "(Service may have crashed.)"
1018 << (tries > 1 ? " Retrying..." : "");
1019 cache.invalidate();
1020 continue;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001021 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001022 if (wasMapped) {
1023 LOG(INFO) << "\"" << key << "\" became invalid in service \""
1024 << client->getName() << "\". Retrying...";
1025 wasMapped = false;
1026 }
1027 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001028 }
1029 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001030 return status; // return the last status from a valid client
Pawin Vongmasa36653902018-11-15 00:10:25 -08001031}
1032
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001033c2_status_t Codec2Client::CreateComponentByName(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001034 const char* componentName,
1035 const std::shared_ptr<Listener>& listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001036 std::shared_ptr<Component>* component,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001037 std::shared_ptr<Codec2Client>* owner,
1038 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001039 std::string key{"create:"};
1040 key.append(componentName);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001041 c2_status_t status = ForAllServices(
1042 key,
1043 numberOfAttempts,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001044 [owner, component, componentName, &listener](
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001045 const std::shared_ptr<Codec2Client> &client)
1046 -> c2_status_t {
1047 c2_status_t status = client->createComponent(componentName,
1048 listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001049 component);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001050 if (status == C2_OK) {
1051 if (owner) {
1052 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001053 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001054 } else if (status != C2_NOT_FOUND) {
1055 LOG(DEBUG) << "IComponentStore("
1056 << client->getServiceName()
1057 << ")::createComponent(\"" << componentName
1058 << "\") returned status = "
1059 << status << ".";
1060 }
1061 return status;
1062 });
1063 if (status != C2_OK) {
1064 LOG(DEBUG) << "Failed to create component \"" << componentName
1065 << "\" from all known services. "
1066 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001067 }
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001068 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001069}
1070
1071std::shared_ptr<Codec2Client::Interface>
1072 Codec2Client::CreateInterfaceByName(
1073 const char* interfaceName,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001074 std::shared_ptr<Codec2Client>* owner,
1075 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001076 std::string key{"create:"};
1077 key.append(interfaceName);
1078 std::shared_ptr<Interface> interface;
1079 c2_status_t status = ForAllServices(
1080 key,
1081 numberOfAttempts,
1082 [owner, &interface, interfaceName](
1083 const std::shared_ptr<Codec2Client> &client)
1084 -> c2_status_t {
1085 c2_status_t status = client->createInterface(interfaceName,
1086 &interface);
1087 if (status == C2_OK) {
1088 if (owner) {
1089 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001090 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001091 } else if (status != C2_NOT_FOUND) {
1092 LOG(DEBUG) << "IComponentStore("
1093 << client->getServiceName()
1094 << ")::createInterface(\"" << interfaceName
1095 << "\") returned status = "
1096 << status << ".";
1097 }
1098 return status;
1099 });
1100 if (status != C2_OK) {
1101 LOG(DEBUG) << "Failed to create interface \"" << interfaceName
1102 << "\" from all known services. "
1103 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001104 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001105 return interface;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001106}
1107
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001108std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
1109 static std::vector<C2Component::Traits> sList{[]() {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001110 std::vector<C2Component::Traits> list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001111 for (Cache& cache : Cache::List()) {
1112 std::vector<C2Component::Traits> const& traits = cache.getTraits();
1113 list.insert(list.end(), traits.begin(), traits.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001114 }
1115 return list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001116 }()};
1117 return sList;
1118}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001119
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001120std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
1121 char const* serviceName) {
Pawin Vongmasa18588322019-05-18 01:52:13 -07001122 int32_t inputSurfaceSetting = ::android::base::GetIntProperty(
1123 "debug.stagefright.c2inputsurface", int32_t(0));
1124 if (inputSurfaceSetting <= 0) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001125 return nullptr;
1126 }
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001127 size_t index = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001128 if (serviceName) {
1129 index = getServiceIndex(serviceName);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001130 if (index == GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001131 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
1132 << serviceName << "\"";
1133 }
1134 }
1135
1136 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001137 if (index != GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001138 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
1139 if (client->createInputSurface(&inputSurface) == C2_OK) {
1140 return inputSurface;
1141 }
1142 }
1143 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
1144 "from all services...";
1145 for (Cache& cache : Cache::List()) {
1146 std::shared_ptr<Codec2Client> client = cache.getClient();
1147 if (client->createInputSurface(&inputSurface) == C2_OK) {
1148 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
1149 "service \"" << client->getServiceName() << "\"";
1150 return inputSurface;
1151 }
1152 }
1153 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
1154 "from all services";
1155 return nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001156}
1157
1158// Codec2Client::Listener
1159
1160Codec2Client::Listener::~Listener() {
1161}
1162
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001163// Codec2Client::Interface
1164Codec2Client::Interface::Interface(const sp<Base>& base)
1165 : Configurable{
1166 [base]() -> sp<IConfigurable> {
1167 Return<sp<IConfigurable>> transResult =
1168 base->getConfigurable();
1169 return transResult.isOk() ?
1170 static_cast<sp<IConfigurable>>(transResult) :
1171 nullptr;
1172 }()
1173 },
1174 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001175}
1176
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001177// Codec2Client::Component
1178Codec2Client::Component::Component(const sp<Base>& base)
1179 : Configurable{
1180 [base]() -> sp<IConfigurable> {
1181 Return<sp<IComponentInterface>> transResult1 =
1182 base->getInterface();
1183 if (!transResult1.isOk()) {
1184 return nullptr;
1185 }
1186 Return<sp<IConfigurable>> transResult2 =
1187 static_cast<sp<IComponentInterface>>(transResult1)->
1188 getConfigurable();
1189 return transResult2.isOk() ?
1190 static_cast<sp<IConfigurable>>(transResult2) :
1191 nullptr;
1192 }()
1193 },
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001194 mBase1_0{base},
1195 mBase1_1{Base1_1::castFrom(base)},
1196 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1197 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1198}
1199
1200Codec2Client::Component::Component(const sp<Base1_1>& base)
1201 : Configurable{
1202 [base]() -> sp<IConfigurable> {
1203 Return<sp<IComponentInterface>> transResult1 =
1204 base->getInterface();
1205 if (!transResult1.isOk()) {
1206 return nullptr;
1207 }
1208 Return<sp<IConfigurable>> transResult2 =
1209 static_cast<sp<IComponentInterface>>(transResult1)->
1210 getConfigurable();
1211 return transResult2.isOk() ?
1212 static_cast<sp<IConfigurable>>(transResult2) :
1213 nullptr;
1214 }()
1215 },
1216 mBase1_0{base},
1217 mBase1_1{base},
1218 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1219 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001220}
1221
1222Codec2Client::Component::~Component() {
1223}
1224
1225c2_status_t Codec2Client::Component::createBlockPool(
1226 C2Allocator::id_t id,
1227 C2BlockPool::local_id_t* blockPoolId,
1228 std::shared_ptr<Codec2Client::Configurable>* configurable) {
1229 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001230 Return<void> transStatus = mBase1_0->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001231 static_cast<uint32_t>(id),
1232 [&status, blockPoolId, configurable](
1233 Status s,
1234 uint64_t pId,
1235 const sp<IConfigurable>& c) {
1236 status = static_cast<c2_status_t>(s);
1237 configurable->reset();
1238 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001239 LOG(DEBUG) << "createBlockPool -- call failed: "
1240 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001241 return;
1242 }
1243 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001244 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001245 });
1246 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001247 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001248 return C2_TRANSACTION_FAILED;
1249 }
1250 return status;
1251}
1252
1253c2_status_t Codec2Client::Component::destroyBlockPool(
1254 C2BlockPool::local_id_t localId) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001255 Return<Status> transResult = mBase1_0->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001256 static_cast<uint64_t>(localId));
1257 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001258 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001259 return C2_TRANSACTION_FAILED;
1260 }
1261 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1262}
1263
Wonsik Kimab34ed62019-01-31 15:28:46 -08001264void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001265 const std::list<std::unique_ptr<C2Work>> &workItems) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001266 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001267 mOutputBufferQueue->holdBufferQueueBlocks(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001268}
1269
1270c2_status_t Codec2Client::Component::queue(
1271 std::list<std::unique_ptr<C2Work>>* const items) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001272 WorkBundle workBundle;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001273 if (!objcpy(&workBundle, *items, mBufferPoolSender.get())) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001274 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001275 return C2_TRANSACTION_FAILED;
1276 }
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001277 Return<Status> transStatus = mBase1_0->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001278 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001279 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001280 return C2_TRANSACTION_FAILED;
1281 }
1282 c2_status_t status =
1283 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1284 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001285 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001286 }
1287 return status;
1288}
1289
1290c2_status_t Codec2Client::Component::flush(
1291 C2Component::flush_mode_t mode,
1292 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
1293 (void)mode; // Flush mode isn't supported in HIDL yet.
1294 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001295 Return<void> transStatus = mBase1_0->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001296 [&status, flushedWork](
1297 Status s, const WorkBundle& wb) {
1298 status = static_cast<c2_status_t>(s);
1299 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001300 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001301 return;
1302 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001303 if (!objcpy(flushedWork, wb)) {
1304 status = C2_CORRUPTED;
1305 } else {
1306 status = C2_OK;
1307 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001308 });
1309 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001310 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001311 return C2_TRANSACTION_FAILED;
1312 }
1313
1314 // Indices of flushed work items.
1315 std::vector<uint64_t> flushedIndices;
1316 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
1317 if (work) {
1318 if (work->worklets.empty()
1319 || !work->worklets.back()
1320 || (work->worklets.back()->output.flags &
1321 C2FrameData::FLAG_INCOMPLETE) == 0) {
1322 // input is complete
1323 flushedIndices.emplace_back(
1324 work->input.ordinal.frameIndex.peeku());
1325 }
1326 }
1327 }
1328
Pawin Vongmasa36653902018-11-15 00:10:25 -08001329 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001330 mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001331
1332 return status;
1333}
1334
1335c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001336 Return<Status> transStatus = mBase1_0->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001337 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1338 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001339 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001340 return C2_TRANSACTION_FAILED;
1341 }
1342 c2_status_t status =
1343 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1344 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001345 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001346 }
1347 return status;
1348}
1349
1350c2_status_t Codec2Client::Component::start() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001351 Return<Status> transStatus = mBase1_0->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001352 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001353 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001354 return C2_TRANSACTION_FAILED;
1355 }
1356 c2_status_t status =
1357 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1358 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001359 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001360 }
1361 return status;
1362}
1363
1364c2_status_t Codec2Client::Component::stop() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001365 Return<Status> transStatus = mBase1_0->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001366 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001367 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001368 return C2_TRANSACTION_FAILED;
1369 }
1370 c2_status_t status =
1371 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1372 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001373 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001374 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001375 return status;
1376}
1377
1378c2_status_t Codec2Client::Component::reset() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001379 Return<Status> transStatus = mBase1_0->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001380 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001381 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001382 return C2_TRANSACTION_FAILED;
1383 }
1384 c2_status_t status =
1385 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1386 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001387 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001388 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001389 return status;
1390}
1391
1392c2_status_t Codec2Client::Component::release() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001393 Return<Status> transStatus = mBase1_0->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001394 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001395 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001396 return C2_TRANSACTION_FAILED;
1397 }
1398 c2_status_t status =
1399 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1400 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001401 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001402 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001403 return status;
1404}
1405
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001406c2_status_t Codec2Client::Component::configureVideoTunnel(
1407 uint32_t avSyncHwId,
1408 native_handle_t** sidebandHandle) {
1409 *sidebandHandle = nullptr;
1410 if (!mBase1_1) {
1411 return C2_OMITTED;
1412 }
1413 c2_status_t status{};
1414 Return<void> transStatus = mBase1_1->configureVideoTunnel(avSyncHwId,
1415 [&status, sidebandHandle](
1416 Status s, hardware::hidl_handle const& h) {
1417 status = static_cast<c2_status_t>(s);
1418 if (h.getNativeHandle()) {
1419 *sidebandHandle = native_handle_clone(h.getNativeHandle());
1420 }
1421 });
1422 if (!transStatus.isOk()) {
1423 LOG(ERROR) << "configureVideoTunnel -- transaction failed.";
1424 return C2_TRANSACTION_FAILED;
1425 }
1426 return status;
1427}
1428
Pawin Vongmasa36653902018-11-15 00:10:25 -08001429c2_status_t Codec2Client::Component::setOutputSurface(
1430 C2BlockPool::local_id_t blockPoolId,
1431 const sp<IGraphicBufferProducer>& surface,
1432 uint32_t generation) {
Sungtak Lee08515812019-06-05 11:16:32 -07001433 uint64_t bqId = 0;
1434 sp<IGraphicBufferProducer> nullIgbp;
1435 sp<HGraphicBufferProducer2> nullHgbp;
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08001436
Sungtak Lee08515812019-06-05 11:16:32 -07001437 sp<HGraphicBufferProducer2> igbp = surface ?
1438 surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
1439 if (surface && !igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001440 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001441 }
1442
Sungtak Lee08515812019-06-05 11:16:32 -07001443 if (!surface) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001444 mOutputBufferQueue->configure(nullIgbp, generation, 0);
Sungtak Lee08515812019-06-05 11:16:32 -07001445 } else if (surface->getUniqueId(&bqId) != OK) {
1446 LOG(ERROR) << "setOutputSurface -- "
1447 "cannot obtain bufferqueue id.";
1448 bqId = 0;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001449 mOutputBufferQueue->configure(nullIgbp, generation, 0);
Sungtak Lee08515812019-06-05 11:16:32 -07001450 } else {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001451 mOutputBufferQueue->configure(surface, generation, bqId);
Sungtak Lee08515812019-06-05 11:16:32 -07001452 }
1453 ALOGD("generation remote change %u", generation);
1454
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001455 Return<Status> transStatus = mBase1_0->setOutputSurface(
Sungtak Lee08515812019-06-05 11:16:32 -07001456 static_cast<uint64_t>(blockPoolId),
1457 bqId == 0 ? nullHgbp : igbp);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001458 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001459 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001460 return C2_TRANSACTION_FAILED;
1461 }
1462 c2_status_t status =
1463 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1464 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001465 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001466 }
1467 return status;
1468}
1469
1470status_t Codec2Client::Component::queueToOutputSurface(
1471 const C2ConstGraphicBlock& block,
1472 const QueueBufferInput& input,
1473 QueueBufferOutput* output) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001474 return mOutputBufferQueue->outputBuffer(block, input, output);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001475}
1476
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001477c2_status_t Codec2Client::Component::connectToInputSurface(
1478 const std::shared_ptr<InputSurface>& inputSurface,
1479 std::shared_ptr<InputSurfaceConnection>* connection) {
1480 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001481 Return<void> transStatus = mBase1_0->connectToInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001482 inputSurface->mBase,
1483 [&status, connection](
1484 Status s, const sp<IInputSurfaceConnection>& c) {
1485 status = static_cast<c2_status_t>(s);
1486 if (status != C2_OK) {
1487 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1488 << status << ".";
1489 return;
1490 }
1491 *connection = std::make_shared<InputSurfaceConnection>(c);
1492 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001493 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001494 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001495 return C2_TRANSACTION_FAILED;
1496 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001497 return status;
1498}
1499
1500c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001501 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001502 const sp<HGraphicBufferSource>& source,
1503 std::shared_ptr<InputSurfaceConnection>* connection) {
1504 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001505 Return<void> transStatus = mBase1_0->connectToOmxInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001506 producer, source,
1507 [&status, connection](
1508 Status s, const sp<IInputSurfaceConnection>& c) {
1509 status = static_cast<c2_status_t>(s);
1510 if (status != C2_OK) {
1511 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1512 << status << ".";
1513 return;
1514 }
1515 *connection = std::make_shared<InputSurfaceConnection>(c);
1516 });
1517 if (!transStatus.isOk()) {
1518 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1519 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001520 }
1521 return status;
1522}
1523
1524c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001525 Return<Status> transStatus = mBase1_0->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001526 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001527 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001528 return C2_TRANSACTION_FAILED;
1529 }
1530 c2_status_t status =
1531 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1532 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001533 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1534 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001535 }
1536 return status;
1537}
1538
1539c2_status_t Codec2Client::Component::setDeathListener(
1540 const std::shared_ptr<Component>& component,
1541 const std::shared_ptr<Listener>& listener) {
1542
1543 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1544 std::weak_ptr<Component> component;
1545 std::weak_ptr<Listener> base;
1546
1547 virtual void serviceDied(
1548 uint64_t /* cookie */,
1549 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1550 ) override {
1551 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1552 listener->onDeath(component);
1553 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001554 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001555 }
1556 }
1557 };
1558
1559 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1560 deathRecipient->base = listener;
1561 deathRecipient->component = component;
1562
1563 component->mDeathRecipient = deathRecipient;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001564 Return<bool> transResult = component->mBase1_0->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001565 component->mDeathRecipient, 0);
1566 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001567 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001568 return C2_TRANSACTION_FAILED;
1569 }
1570 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001571 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001572 return C2_CORRUPTED;
1573 }
1574 return C2_OK;
1575}
1576
1577// Codec2Client::InputSurface
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001578Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base)
1579 : Configurable{
1580 [base]() -> sp<IConfigurable> {
1581 Return<sp<IConfigurable>> transResult =
1582 base->getConfigurable();
1583 return transResult.isOk() ?
1584 static_cast<sp<IConfigurable>>(transResult) :
1585 nullptr;
1586 }()
1587 },
1588 mBase{base},
1589 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001590 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
1591 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001592 base->getGraphicBufferProducer();
1593 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001594 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001595 nullptr;
1596 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001597}
1598
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001599sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08001600 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1601 return mGraphicBufferProducer;
1602}
1603
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001604sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001605 return mBase;
1606}
1607
1608// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08001609Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001610 const sp<IInputSurfaceConnection>& base)
1611 : Configurable{
1612 [base]() -> sp<IConfigurable> {
1613 Return<sp<IConfigurable>> transResult =
1614 base->getConfigurable();
1615 return transResult.isOk() ?
1616 static_cast<sp<IConfigurable>>(transResult) :
1617 nullptr;
1618 }()
1619 },
1620 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001621}
1622
1623c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001624 Return<Status> transResult = mBase->disconnect();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001625 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1626}
1627
1628} // namespace android
1629