blob: 0a61fe24677686dabeefb440623db31bb1f53b43 [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>
Sungtak Lee8577dab2021-03-12 02:25:50 -080040#include <codec2/hidl/1.2/types.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070041
42#include <cutils/native_handle.h>
43#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
44#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
45#include <hidl/HidlSupport.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080046
47#include <deque>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070048#include <iterator>
Pawin Vongmasa36653902018-11-15 00:10:25 -080049#include <limits>
50#include <map>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070051#include <mutex>
52#include <sstream>
53#include <thread>
Pawin Vongmasa36653902018-11-15 00:10:25 -080054#include <type_traits>
55#include <vector>
56
Pawin Vongmasa36653902018-11-15 00:10:25 -080057namespace android {
58
59using ::android::hardware::hidl_vec;
60using ::android::hardware::hidl_string;
61using ::android::hardware::Return;
62using ::android::hardware::Void;
Pawin Vongmasa36653902018-11-15 00:10:25 -080063
Pawin Vongmasabf69de92019-10-29 06:21:27 -070064using namespace ::android::hardware::media::c2::V1_1;
65using namespace ::android::hardware::media::c2::V1_1::utils;
Sungtak Leed3318082018-09-07 15:52:43 -070066using namespace ::android::hardware::media::bufferpool::V2_0;
67using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
Pawin Vongmasa36653902018-11-15 00:10:25 -080068
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080069using HGraphicBufferProducer1 = ::android::hardware::graphics::bufferqueue::
70 V1_0::IGraphicBufferProducer;
71using HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
72 V2_0::IGraphicBufferProducer;
73using B2HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
74 V2_0::utils::B2HGraphicBufferProducer;
75using H2BGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
76 V2_0::utils::H2BGraphicBufferProducer;
77
Pawin Vongmasa36653902018-11-15 00:10:25 -080078namespace /* unnamed */ {
79
80// c2_status_t value that corresponds to hwbinder transaction failure.
81constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
82
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070083// Searches for a name in GetServiceNames() and returns the index found. If the
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070084// name is not found, the returned index will be equal to
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070085// GetServiceNames().size().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070086size_t getServiceIndex(char const* name) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070087 std::vector<std::string> const& names = Codec2Client::GetServiceNames();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070088 size_t i = 0;
89 for (; i < names.size(); ++i) {
90 if (name == names[i]) {
91 break;
92 }
Pawin Vongmasa36653902018-11-15 00:10:25 -080093 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070094 return i;
Pawin Vongmasa36653902018-11-15 00:10:25 -080095}
96
Pawin Vongmasa83d2c552020-03-05 04:36:08 -080097class Client2Store : public C2ComponentStore {
98 std::shared_ptr<Codec2Client> mClient;
99
100public:
101 Client2Store(std::shared_ptr<Codec2Client> const& client)
102 : mClient(client) { }
103
104 virtual ~Client2Store() = default;
105
106 virtual c2_status_t config_sm(
107 std::vector<C2Param*> const &params,
108 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
109 return mClient->config(params, C2_MAY_BLOCK, failures);
110 };
111
112 virtual c2_status_t copyBuffer(
113 std::shared_ptr<C2GraphicBuffer>,
114 std::shared_ptr<C2GraphicBuffer>) {
115 return C2_OMITTED;
116 }
117
118 virtual c2_status_t createComponent(
119 C2String, std::shared_ptr<C2Component>* const component) {
120 component->reset();
121 return C2_OMITTED;
122 }
123
124 virtual c2_status_t createInterface(
125 C2String, std::shared_ptr<C2ComponentInterface>* const interface) {
126 interface->reset();
127 return C2_OMITTED;
128 }
129
130 virtual c2_status_t query_sm(
131 std::vector<C2Param*> const& stackParams,
132 std::vector<C2Param::Index> const& heapParamIndices,
133 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
134 return mClient->query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
135 }
136
137 virtual c2_status_t querySupportedParams_nb(
138 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
139 return mClient->querySupportedParams(params);
140 }
141
142 virtual c2_status_t querySupportedValues_sm(
143 std::vector<C2FieldSupportedValuesQuery>& fields) const {
144 return mClient->querySupportedValues(fields, C2_MAY_BLOCK);
145 }
146
147 virtual C2String getName() const {
148 return mClient->getName();
149 }
150
151 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const {
152 return mClient->getParamReflector();
153 }
154
155 virtual std::vector<std::shared_ptr<C2Component::Traits const>> listComponents() {
156 return std::vector<std::shared_ptr<C2Component::Traits const>>();
157 }
158};
159
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700160} // unnamed namespace
161
162// This class caches a Codec2Client object and its component traits. The client
163// will be created the first time it is needed, and it can be refreshed if the
164// service dies (by calling invalidate()). The first time listComponents() is
165// called from the client, the result will be cached.
166class Codec2Client::Cache {
167 // Cached client
168 std::shared_ptr<Codec2Client> mClient;
169 mutable std::mutex mClientMutex;
170
171 // Cached component traits
172 std::vector<C2Component::Traits> mTraits;
173 std::once_flag mTraitsInitializationFlag;
174
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700175 // The index of the service. This is based on GetServiceNames().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700176 size_t mIndex;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700177 // Called by s() exactly once to initialize the cache. The index must be a
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700178 // valid index into the vector returned by GetServiceNames(). Calling
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700179 // init(index) will associate the cache to the service with name
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700180 // GetServiceNames()[index].
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700181 void init(size_t index) {
182 mIndex = index;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700183 }
184
185public:
186 Cache() = default;
187
188 // Initializes mClient if needed, then returns mClient.
189 // If the service is unavailable but listed in the manifest, this function
190 // will block indefinitely.
191 std::shared_ptr<Codec2Client> getClient() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700192 std::scoped_lock lock{mClientMutex};
193 if (!mClient) {
194 mClient = Codec2Client::_CreateFromIndex(mIndex);
195 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700196 CHECK(mClient) << "Failed to create Codec2Client to service \""
197 << GetServiceNames()[mIndex] << "\". (Index = "
198 << mIndex << ").";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700199 return mClient;
200 }
201
202 // Causes a subsequent call to getClient() to create a new client. This
203 // function should be called after the service dies.
204 //
205 // Note: This function is called only by ForAllServices().
206 void invalidate() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700207 std::scoped_lock lock{mClientMutex};
208 mClient = nullptr;
209 }
210
211 // Returns a list of traits for components supported by the service. This
212 // list is cached.
213 std::vector<C2Component::Traits> const& getTraits() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700214 std::call_once(mTraitsInitializationFlag, [this]() {
215 bool success{false};
216 // Spin until _listComponents() is successful.
217 while (true) {
218 std::shared_ptr<Codec2Client> client = getClient();
219 mTraits = client->_listComponents(&success);
220 if (success) {
221 break;
222 }
Pawin Vongmasa21617db2020-04-24 06:16:42 -0700223 invalidate();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700224 using namespace std::chrono_literals;
225 static constexpr auto kServiceRetryPeriod = 5s;
226 LOG(INFO) << "Failed to retrieve component traits from service "
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700227 "\"" << GetServiceNames()[mIndex] << "\". "
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700228 "Retrying...";
229 std::this_thread::sleep_for(kServiceRetryPeriod);
230 }
231 });
232 return mTraits;
233 }
234
235 // List() returns the list of all caches.
236 static std::vector<Cache>& List() {
237 static std::vector<Cache> sCaches{[]() {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700238 size_t numServices = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700239 std::vector<Cache> caches(numServices);
240 for (size_t i = 0; i < numServices; ++i) {
241 caches[i].init(i);
242 }
243 return caches;
244 }()};
245 return sCaches;
246 }
247};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800248
249// Codec2ConfigurableClient
250
251const C2String& Codec2ConfigurableClient::getName() const {
252 return mName;
253}
254
Pawin Vongmasa36653902018-11-15 00:10:25 -0800255Codec2ConfigurableClient::Codec2ConfigurableClient(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800256 const sp<IConfigurable>& base)
257 : mBase{base},
258 mName{[base]() -> C2String {
259 C2String outName;
260 Return<void> transStatus = base->getName(
261 [&outName](const hidl_string& name) {
262 outName = name.c_str();
263 });
264 return transStatus.isOk() ? outName : "";
265 }()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800266}
267
268c2_status_t Codec2ConfigurableClient::query(
269 const std::vector<C2Param*> &stackParams,
270 const std::vector<C2Param::Index> &heapParamIndices,
271 c2_blocking_t mayBlock,
272 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
273 hidl_vec<ParamIndex> indices(
274 stackParams.size() + heapParamIndices.size());
275 size_t numIndices = 0;
276 for (C2Param* const& stackParam : stackParams) {
277 if (!stackParam) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800278 LOG(WARNING) << "query -- null stack param encountered.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800279 continue;
280 }
281 indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
282 }
283 size_t numStackIndices = numIndices;
284 for (const C2Param::Index& index : heapParamIndices) {
285 indices[numIndices++] =
286 static_cast<ParamIndex>(static_cast<uint32_t>(index));
287 }
288 indices.resize(numIndices);
289 if (heapParams) {
290 heapParams->reserve(heapParams->size() + numIndices);
291 }
292 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800293 Return<void> transStatus = mBase->query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800294 indices,
295 mayBlock == C2_MAY_BLOCK,
296 [&status, &numStackIndices, &stackParams, heapParams](
297 Status s, const Params& p) {
298 status = static_cast<c2_status_t>(s);
299 if (status != C2_OK && status != C2_BAD_INDEX) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800300 LOG(DEBUG) << "query -- call failed: "
301 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800302 return;
303 }
304 std::vector<C2Param*> paramPointers;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800305 if (!parseParamsBlob(&paramPointers, p)) {
306 LOG(ERROR) << "query -- error while parsing params.";
307 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800308 return;
309 }
310 size_t i = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800311 for (auto it = paramPointers.begin();
312 it != paramPointers.end(); ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800313 C2Param* paramPointer = *it;
314 if (numStackIndices > 0) {
315 --numStackIndices;
316 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800317 LOG(WARNING) << "query -- null stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800318 ++it;
319 continue;
320 }
321 for (; i < stackParams.size() && !stackParams[i]; ) {
322 ++i;
323 }
324 if (i >= stackParams.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800325 LOG(ERROR) << "query -- unexpected error.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800326 status = C2_CORRUPTED;
327 return;
328 }
329 if (stackParams[i]->index() != paramPointer->index()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800330 LOG(WARNING) << "query -- param skipped: "
331 "index = "
332 << stackParams[i]->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800333 stackParams[i++]->invalidate();
334 continue;
335 }
336 if (!stackParams[i++]->updateFrom(*paramPointer)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800337 LOG(WARNING) << "query -- param update failed: "
338 "index = "
339 << paramPointer->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800340 }
341 } else {
342 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800343 LOG(WARNING) << "query -- null heap param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800344 ++it;
345 continue;
346 }
347 if (!heapParams) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800348 LOG(WARNING) << "query -- "
349 "unexpected extra stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800350 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800351 heapParams->emplace_back(
352 C2Param::Copy(*paramPointer));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800353 }
354 }
355 ++it;
356 }
357 });
358 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800359 LOG(ERROR) << "query -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800360 return C2_TRANSACTION_FAILED;
361 }
362 return status;
363}
364
365c2_status_t Codec2ConfigurableClient::config(
366 const std::vector<C2Param*> &params,
367 c2_blocking_t mayBlock,
368 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
369 Params hidlParams;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800370 if (!createParamsBlob(&hidlParams, params)) {
371 LOG(ERROR) << "config -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800372 return C2_TRANSACTION_FAILED;
373 }
374 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800375 Return<void> transStatus = mBase->config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800376 hidlParams,
377 mayBlock == C2_MAY_BLOCK,
378 [&status, &params, failures](
379 Status s,
380 const hidl_vec<SettingResult> f,
381 const Params& o) {
382 status = static_cast<c2_status_t>(s);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800383 if (status != C2_OK && status != C2_BAD_INDEX) {
384 LOG(DEBUG) << "config -- call failed: "
385 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800386 }
387 size_t i = failures->size();
388 failures->resize(i + f.size());
389 for (const SettingResult& sf : f) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800390 if (!objcpy(&(*failures)[i++], sf)) {
391 LOG(ERROR) << "config -- "
392 << "invalid SettingResult returned.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800393 return;
394 }
395 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800396 if (!updateParamsFromBlob(params, o)) {
397 LOG(ERROR) << "config -- "
398 << "failed to parse returned params.";
399 status = C2_CORRUPTED;
400 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800401 });
402 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800403 LOG(ERROR) << "config -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800404 return C2_TRANSACTION_FAILED;
405 }
406 return status;
407}
408
409c2_status_t Codec2ConfigurableClient::querySupportedParams(
410 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
411 // TODO: Cache and query properly!
412 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800413 Return<void> transStatus = mBase->querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800414 std::numeric_limits<uint32_t>::min(),
415 std::numeric_limits<uint32_t>::max(),
416 [&status, params](
417 Status s,
418 const hidl_vec<ParamDescriptor>& p) {
419 status = static_cast<c2_status_t>(s);
420 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800421 LOG(DEBUG) << "querySupportedParams -- call failed: "
422 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800423 return;
424 }
425 size_t i = params->size();
426 params->resize(i + p.size());
427 for (const ParamDescriptor& sp : p) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800428 if (!objcpy(&(*params)[i++], sp)) {
429 LOG(ERROR) << "querySupportedParams -- "
430 << "invalid returned ParamDescriptor.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800431 return;
432 }
433 }
434 });
435 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800436 LOG(ERROR) << "querySupportedParams -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800437 return C2_TRANSACTION_FAILED;
438 }
439 return status;
440}
441
442c2_status_t Codec2ConfigurableClient::querySupportedValues(
443 std::vector<C2FieldSupportedValuesQuery>& fields,
444 c2_blocking_t mayBlock) const {
445 hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
446 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800447 if (!objcpy(&inFields[i], fields[i])) {
448 LOG(ERROR) << "querySupportedValues -- bad input";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800449 return C2_TRANSACTION_FAILED;
450 }
451 }
452
453 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800454 Return<void> transStatus = mBase->querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800455 inFields,
456 mayBlock == C2_MAY_BLOCK,
457 [&status, &inFields, &fields](
458 Status s,
459 const hidl_vec<FieldSupportedValuesQueryResult>& r) {
460 status = static_cast<c2_status_t>(s);
461 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800462 LOG(DEBUG) << "querySupportedValues -- call failed: "
463 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800464 return;
465 }
466 if (r.size() != fields.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800467 LOG(ERROR) << "querySupportedValues -- "
468 "input and output lists "
469 "have different sizes.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800470 status = C2_CORRUPTED;
471 return;
472 }
473 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800474 if (!objcpy(&fields[i], inFields[i], r[i])) {
475 LOG(ERROR) << "querySupportedValues -- "
476 "invalid returned value.";
477 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800478 return;
479 }
480 }
481 });
482 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800483 LOG(ERROR) << "querySupportedValues -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800484 return C2_TRANSACTION_FAILED;
485 }
486 return status;
487}
488
489// Codec2Client::Component::HidlListener
490struct Codec2Client::Component::HidlListener : public IComponentListener {
491 std::weak_ptr<Component> component;
492 std::weak_ptr<Listener> base;
493
494 virtual Return<void> onWorkDone(const WorkBundle& workBundle) override {
495 std::list<std::unique_ptr<C2Work>> workItems;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800496 if (!objcpy(&workItems, workBundle)) {
497 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800498 return Void();
499 }
500 // release input buffers potentially held by the component from queue
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800501 std::shared_ptr<Codec2Client::Component> strongComponent =
502 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800503 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800504 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800505 }
506 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800507 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800508 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800509 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800510 }
511 return Void();
512 }
513
514 virtual Return<void> onTripped(
515 const hidl_vec<SettingResult>& settingResults) override {
516 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
517 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800518 for (size_t i = 0; i < settingResults.size(); ++i) {
519 std::unique_ptr<C2SettingResult> c2SettingResult;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800520 if (!objcpy(&c2SettingResult, settingResults[i])) {
521 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800522 return Void();
523 }
524 c2SettingResults[i] = std::move(c2SettingResult);
525 }
526 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
527 listener->onTripped(component, c2SettingResults);
528 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800529 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800530 }
531 return Void();
532 }
533
534 virtual Return<void> onError(Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800535 LOG(DEBUG) << "onError --"
536 << " status = " << s
537 << ", errorCode = " << errorCode
538 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800539 if (std::shared_ptr<Listener> listener = base.lock()) {
540 listener->onError(component, s == Status::OK ?
541 errorCode : static_cast<c2_status_t>(s));
542 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800543 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800544 }
545 return Void();
546 }
547
548 virtual Return<void> onFramesRendered(
549 const hidl_vec<RenderedFrame>& renderedFrames) override {
550 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800551 if (!listener) {
552 LOG(DEBUG) << "onFramesRendered -- listener died.";
553 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800554 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800555 for (const RenderedFrame& renderedFrame : renderedFrames) {
556 listener->onFrameRendered(
557 renderedFrame.bufferQueueId,
558 renderedFrame.slotId,
559 renderedFrame.timestampNs);
560 }
561 return Void();
562 }
563
564 virtual Return<void> onInputBuffersReleased(
565 const hidl_vec<InputBuffer>& inputBuffers) override {
566 std::shared_ptr<Listener> listener = base.lock();
567 if (!listener) {
568 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
569 return Void();
570 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800571 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800572 LOG(VERBOSE) << "onInputBuffersReleased --"
573 " received death notification of"
574 " input buffer:"
575 " frameIndex = " << inputBuffer.frameIndex
576 << ", bufferIndex = " << inputBuffer.arrayIndex
577 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -0800578 listener->onInputBufferDone(
579 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800580 }
581 return Void();
582 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800583
Pawin Vongmasa36653902018-11-15 00:10:25 -0800584};
585
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700586// Codec2Client::Component::BufferPoolSender
587struct Codec2Client::Component::BufferPoolSender :
588 hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
589 BufferPoolSender()
590 : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
591 }
592};
593
594// Codec2Client::Component::OutputBufferQueue
595struct Codec2Client::Component::OutputBufferQueue :
596 hardware::media::c2::V1_1::utils::OutputBufferQueue {
597 OutputBufferQueue()
598 : hardware::media::c2::V1_1::utils::OutputBufferQueue() {
599 }
600};
601
Pawin Vongmasa36653902018-11-15 00:10:25 -0800602// Codec2Client
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700603Codec2Client::Codec2Client(sp<Base> const& base,
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700604 size_t serviceIndex)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800605 : Configurable{
606 [base]() -> sp<IConfigurable> {
607 Return<sp<IConfigurable>> transResult =
608 base->getConfigurable();
609 return transResult.isOk() ?
610 static_cast<sp<IConfigurable>>(transResult) :
611 nullptr;
612 }()
613 },
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700614 mBase1_0{base},
615 mBase1_1{Base1_1::castFrom(base)},
Sungtak Lee8577dab2021-03-12 02:25:50 -0800616 mBase1_2{Base1_2::castFrom(base)},
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700617 mServiceIndex{serviceIndex} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800618 Return<sp<IClientManager>> transResult = base->getPoolClientManager();
619 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800620 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800621 } else {
622 mHostPoolManager = static_cast<sp<IClientManager>>(transResult);
623 }
624}
625
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700626sp<Codec2Client::Base> const& Codec2Client::getBase() const {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700627 return mBase1_0;
628}
629
630sp<Codec2Client::Base1_0> const& Codec2Client::getBase1_0() const {
631 return mBase1_0;
632}
633
634sp<Codec2Client::Base1_1> const& Codec2Client::getBase1_1() const {
635 return mBase1_1;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700636}
637
Sungtak Lee8577dab2021-03-12 02:25:50 -0800638sp<Codec2Client::Base1_2> const& Codec2Client::getBase1_2() const {
639 return mBase1_2;
640}
641
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700642std::string const& Codec2Client::getServiceName() const {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700643 return GetServiceNames()[mServiceIndex];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700644}
645
Pawin Vongmasa36653902018-11-15 00:10:25 -0800646c2_status_t Codec2Client::createComponent(
647 const C2String& name,
648 const std::shared_ptr<Codec2Client::Listener>& listener,
649 std::shared_ptr<Codec2Client::Component>* const component) {
650
Pawin Vongmasa36653902018-11-15 00:10:25 -0800651 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800652 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800653 hidlListener->base = listener;
Sungtak Lee8577dab2021-03-12 02:25:50 -0800654 Return<void> transStatus;
655 if (mBase1_2) {
656 transStatus = mBase1_2->createComponent_1_2(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800657 name,
658 hidlListener,
659 ClientManager::getInstance(),
660 [&status, component, hidlListener](
661 Status s,
662 const sp<IComponent>& c) {
663 status = static_cast<c2_status_t>(s);
664 if (status != C2_OK) {
665 return;
666 }
667 *component = std::make_shared<Codec2Client::Component>(c);
668 hidlListener->component = *component;
Sungtak Lee8577dab2021-03-12 02:25:50 -0800669 });
670 }
671 else if (mBase1_1) {
672 transStatus = mBase1_1->createComponent_1_1(
673 name,
674 hidlListener,
675 ClientManager::getInstance(),
676 [&status, component, hidlListener](
677 Status s,
678 const sp<IComponent>& c) {
679 status = static_cast<c2_status_t>(s);
680 if (status != C2_OK) {
681 return;
682 }
683 *component = std::make_shared<Codec2Client::Component>(c);
684 hidlListener->component = *component;
685 });
686 } else if (mBase1_0) { // ver1_0
687 transStatus = mBase1_0->createComponent(
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700688 name,
689 hidlListener,
690 ClientManager::getInstance(),
691 [&status, component, hidlListener](
692 Status s,
693 const sp<hardware::media::c2::V1_0::IComponent>& c) {
694 status = static_cast<c2_status_t>(s);
695 if (status != C2_OK) {
696 return;
697 }
698 *component = std::make_shared<Codec2Client::Component>(c);
699 hidlListener->component = *component;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800700 });
Sungtak Lee8577dab2021-03-12 02:25:50 -0800701 } else {
702 status = C2_CORRUPTED;
703 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800704 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800705 LOG(ERROR) << "createComponent(" << name.c_str()
706 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800707 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800708 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800709 if (status == C2_NOT_FOUND) {
710 LOG(VERBOSE) << "createComponent(" << name.c_str()
711 << ") -- component not found.";
712 } else {
713 LOG(ERROR) << "createComponent(" << name.c_str()
714 << ") -- call failed: " << status << ".";
715 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800716 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800717 } else if (!*component) {
718 LOG(ERROR) << "createComponent(" << name.c_str()
719 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800720 return C2_CORRUPTED;
721 }
722
723 status = (*component)->setDeathListener(*component, listener);
724 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800725 LOG(ERROR) << "createComponent(" << name.c_str()
726 << ") -- failed to set up death listener: "
727 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800728 }
729
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700730 (*component)->mBufferPoolSender->setReceiver(mHostPoolManager);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800731 return status;
732}
733
734c2_status_t Codec2Client::createInterface(
735 const C2String& name,
736 std::shared_ptr<Codec2Client::Interface>* const interface) {
737 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700738 Return<void> transStatus = mBase1_0->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800739 name,
740 [&status, interface](
741 Status s,
742 const sp<IComponentInterface>& i) {
743 status = static_cast<c2_status_t>(s);
744 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800745 return;
746 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800747 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800748 });
749 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800750 LOG(ERROR) << "createInterface(" << name.c_str()
751 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800752 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800753 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800754 if (status == C2_NOT_FOUND) {
755 LOG(VERBOSE) << "createInterface(" << name.c_str()
756 << ") -- component not found.";
757 } else {
758 LOG(ERROR) << "createInterface(" << name.c_str()
759 << ") -- call failed: " << status << ".";
760 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800761 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800762 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800763
Pawin Vongmasa36653902018-11-15 00:10:25 -0800764 return status;
765}
766
767c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800768 std::shared_ptr<InputSurface>* const inputSurface) {
769 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700770 Return<void> transStatus = mBase1_0->createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800771 [&status, inputSurface](
772 Status s,
773 const sp<IInputSurface>& i) {
774 status = static_cast<c2_status_t>(s);
775 if (status != C2_OK) {
776 return;
777 }
778 *inputSurface = std::make_shared<InputSurface>(i);
779 });
780 if (!transStatus.isOk()) {
781 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800782 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800783 } else if (status != C2_OK) {
784 LOG(DEBUG) << "createInputSurface -- call failed: "
785 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800786 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800787 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800788}
789
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700790std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
791 return Cache::List()[mServiceIndex].getTraits();
792}
793
794std::vector<C2Component::Traits> Codec2Client::_listComponents(
795 bool* success) const {
796 std::vector<C2Component::Traits> traits;
797 std::string const& serviceName = getServiceName();
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700798 Return<void> transStatus = mBase1_0->listComponents(
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700799 [&traits, &serviceName](Status s,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800800 const hidl_vec<IComponentStore::ComponentTraits>& t) {
801 if (s != Status::OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700802 LOG(DEBUG) << "_listComponents -- call failed: "
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800803 << static_cast<c2_status_t>(s) << ".";
804 return;
805 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700806 traits.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800807 for (size_t i = 0; i < t.size(); ++i) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700808 if (!objcpy(&traits[i], t[i])) {
809 LOG(ERROR) << "_listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800810 return;
811 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700812 traits[i].owner = serviceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800813 }
814 });
815 if (!transStatus.isOk()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700816 LOG(ERROR) << "_listComponents -- transaction failed.";
817 *success = false;
818 } else {
819 *success = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800820 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700821 return traits;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800822}
823
824c2_status_t Codec2Client::copyBuffer(
825 const std::shared_ptr<C2Buffer>& src,
826 const std::shared_ptr<C2Buffer>& dst) {
827 // TODO: Implement?
828 (void)src;
829 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800830 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800831 return C2_OMITTED;
832}
833
834std::shared_ptr<C2ParamReflector>
835 Codec2Client::getParamReflector() {
836 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
837 // should reflect the HAL API.
838 struct SimpleParamReflector : public C2ParamReflector {
839 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
840 hidl_vec<ParamIndex> indices(1);
841 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
842 std::unique_ptr<C2StructDescriptor> descriptor;
843 Return<void> transStatus = mBase->getStructDescriptors(
844 indices,
845 [&descriptor](
846 Status s,
847 const hidl_vec<StructDescriptor>& sd) {
848 c2_status_t status = static_cast<c2_status_t>(s);
849 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800850 LOG(DEBUG) << "SimpleParamReflector -- "
851 "getStructDescriptors() failed: "
852 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800853 descriptor.reset();
854 return;
855 }
856 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800857 LOG(DEBUG) << "SimpleParamReflector -- "
858 "getStructDescriptors() "
859 "returned vector of size "
860 << sd.size() << ". "
861 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800862 descriptor.reset();
863 return;
864 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800865 if (!objcpy(&descriptor, sd[0])) {
866 LOG(DEBUG) << "SimpleParamReflector -- "
867 "getStructDescriptors() returned "
868 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800869 descriptor.reset();
870 return;
871 }
872 });
Wonsik Kim492fecd2020-11-19 11:14:11 -0800873 if (!transStatus.isOk()) {
874 LOG(DEBUG) << "SimpleParamReflector -- transaction failed: "
875 << transStatus.description();
876 descriptor.reset();
877 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800878 return descriptor;
879 }
880
881 SimpleParamReflector(sp<Base> base)
882 : mBase(base) { }
883
884 sp<Base> mBase;
885 };
886
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700887 return std::make_shared<SimpleParamReflector>(mBase1_0);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800888};
889
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700890std::vector<std::string> const& Codec2Client::GetServiceNames() {
891 static std::vector<std::string> sServiceNames{[]() {
892 using ::android::hardware::media::c2::V1_0::IComponentStore;
893 using ::android::hidl::manager::V1_2::IServiceManager;
894
895 while (true) {
896 sp<IServiceManager> serviceManager = IServiceManager::getService();
897 CHECK(serviceManager) << "Hardware service manager is not running.";
898
899 // There are three categories of services based on names.
900 std::vector<std::string> defaultNames; // Prefixed with "default"
901 std::vector<std::string> vendorNames; // Prefixed with "vendor"
902 std::vector<std::string> otherNames; // Others
903 Return<void> transResult;
904 transResult = serviceManager->listManifestByInterface(
905 IComponentStore::descriptor,
906 [&defaultNames, &vendorNames, &otherNames](
907 hidl_vec<hidl_string> const& instanceNames) {
908 for (hidl_string const& instanceName : instanceNames) {
909 char const* name = instanceName.c_str();
910 if (strncmp(name, "default", 7) == 0) {
911 defaultNames.emplace_back(name);
912 } else if (strncmp(name, "vendor", 6) == 0) {
913 vendorNames.emplace_back(name);
914 } else {
915 otherNames.emplace_back(name);
916 }
917 }
918 });
919 if (transResult.isOk()) {
920 // Sort service names in each category.
921 std::sort(defaultNames.begin(), defaultNames.end());
922 std::sort(vendorNames.begin(), vendorNames.end());
923 std::sort(otherNames.begin(), otherNames.end());
924
925 // Concatenate the three lists in this order: default, vendor,
926 // other.
927 std::vector<std::string>& names = defaultNames;
928 names.reserve(names.size() + vendorNames.size() + otherNames.size());
929 names.insert(names.end(),
930 std::make_move_iterator(vendorNames.begin()),
931 std::make_move_iterator(vendorNames.end()));
932 names.insert(names.end(),
933 std::make_move_iterator(otherNames.begin()),
934 std::make_move_iterator(otherNames.end()));
935
936 // Summarize to logcat.
937 if (names.empty()) {
938 LOG(INFO) << "No Codec2 services declared in the manifest.";
939 } else {
940 std::stringstream stringOutput;
941 stringOutput << "Available Codec2 services:";
942 for (std::string const& name : names) {
943 stringOutput << " \"" << name << "\"";
944 }
945 LOG(INFO) << stringOutput.str();
946 }
947
948 return names;
949 }
950 LOG(ERROR) << "Could not retrieve the list of service instances of "
951 << IComponentStore::descriptor
952 << ". Retrying...";
953 }
954 }()};
955 return sServiceNames;
956}
957
Pawin Vongmasa36653902018-11-15 00:10:25 -0800958std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa83d2c552020-03-05 04:36:08 -0800959 const char* name,
960 bool setAsPreferredCodec2ComponentStore) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700961 size_t index = getServiceIndex(name);
Pawin Vongmasa83d2c552020-03-05 04:36:08 -0800962 if (index == GetServiceNames().size()) {
963 if (setAsPreferredCodec2ComponentStore) {
964 LOG(WARNING) << "CreateFromService(" << name
965 << ") -- preferred C2ComponentStore not set.";
966 }
967 return nullptr;
968 }
969 std::shared_ptr<Codec2Client> client = _CreateFromIndex(index);
970 if (setAsPreferredCodec2ComponentStore) {
971 SetPreferredCodec2ComponentStore(
972 std::make_shared<Client2Store>(client));
973 LOG(INFO) << "CreateFromService(" << name
974 << ") -- service set as preferred C2ComponentStore.";
975 }
976 return client;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800977}
978
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700979std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
980 CreateFromAllServices() {
981 std::vector<std::shared_ptr<Codec2Client>> clients(
982 GetServiceNames().size());
983 for (size_t i = GetServiceNames().size(); i > 0; ) {
984 --i;
985 clients[i] = _CreateFromIndex(i);
986 }
987 return clients;
988}
989
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700990std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700991 std::string const& name = GetServiceNames()[index];
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800992 LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700993 sp<Base> baseStore = Base::getService(name);
994 CHECK(baseStore) << "Codec2 service \"" << name << "\""
995 " inaccessible for unknown reasons.";
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800996 LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700997 return std::make_shared<Codec2Client>(baseStore, index);
998}
999
1000c2_status_t Codec2Client::ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001001 const std::string &key,
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001002 size_t numberOfAttempts,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001003 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
1004 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001005 c2_status_t status = C2_NO_INIT; // no IComponentStores present
1006
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001007 // Cache the mapping key -> index of Codec2Client in Cache::List().
Pawin Vongmasa36653902018-11-15 00:10:25 -08001008 static std::mutex key2IndexMutex;
1009 static std::map<std::string, size_t> key2Index;
1010
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001011 // By default try all stores. However, try the last known client first. If
1012 // the last known client fails, retry once. We do this by pushing the last
1013 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -08001014 std::deque<size_t> indices;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001015 for (size_t index = Cache::List().size(); index > 0; ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001016 indices.push_front(--index);
1017 }
1018
1019 bool wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001020 {
1021 std::scoped_lock lock{key2IndexMutex};
1022 auto it = key2Index.find(key);
1023 if (it != key2Index.end()) {
1024 indices.push_front(it->second);
1025 wasMapped = true;
1026 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001027 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001028
1029 for (size_t index : indices) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001030 Cache& cache = Cache::List()[index];
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001031 for (size_t tries = numberOfAttempts; tries > 0; --tries) {
1032 std::shared_ptr<Codec2Client> client{cache.getClient()};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001033 status = predicate(client);
1034 if (status == C2_OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001035 std::scoped_lock lock{key2IndexMutex};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001036 key2Index[key] = index; // update last known client index
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001037 return C2_OK;
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001038 } else if (status == C2_NO_MEMORY) {
1039 return C2_NO_MEMORY;
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001040 } else if (status == C2_TRANSACTION_FAILED) {
1041 LOG(WARNING) << "\"" << key << "\" failed for service \""
1042 << client->getName()
1043 << "\" due to transaction failure. "
1044 << "(Service may have crashed.)"
1045 << (tries > 1 ? " Retrying..." : "");
1046 cache.invalidate();
1047 continue;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001048 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001049 if (wasMapped) {
1050 LOG(INFO) << "\"" << key << "\" became invalid in service \""
1051 << client->getName() << "\". Retrying...";
1052 wasMapped = false;
1053 }
1054 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001055 }
1056 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001057 return status; // return the last status from a valid client
Pawin Vongmasa36653902018-11-15 00:10:25 -08001058}
1059
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001060c2_status_t Codec2Client::CreateComponentByName(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001061 const char* componentName,
1062 const std::shared_ptr<Listener>& listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001063 std::shared_ptr<Component>* component,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001064 std::shared_ptr<Codec2Client>* owner,
1065 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001066 std::string key{"create:"};
1067 key.append(componentName);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001068 c2_status_t status = ForAllServices(
1069 key,
1070 numberOfAttempts,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001071 [owner, component, componentName, &listener](
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001072 const std::shared_ptr<Codec2Client> &client)
1073 -> c2_status_t {
1074 c2_status_t status = client->createComponent(componentName,
1075 listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001076 component);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001077 if (status == C2_OK) {
1078 if (owner) {
1079 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001080 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001081 } else if (status != C2_NOT_FOUND) {
1082 LOG(DEBUG) << "IComponentStore("
1083 << client->getServiceName()
1084 << ")::createComponent(\"" << componentName
1085 << "\") returned status = "
1086 << status << ".";
1087 }
1088 return status;
1089 });
1090 if (status != C2_OK) {
1091 LOG(DEBUG) << "Failed to create component \"" << componentName
1092 << "\" from all known services. "
1093 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001094 }
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001095 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001096}
1097
1098std::shared_ptr<Codec2Client::Interface>
1099 Codec2Client::CreateInterfaceByName(
1100 const char* interfaceName,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001101 std::shared_ptr<Codec2Client>* owner,
1102 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001103 std::string key{"create:"};
1104 key.append(interfaceName);
1105 std::shared_ptr<Interface> interface;
1106 c2_status_t status = ForAllServices(
1107 key,
1108 numberOfAttempts,
1109 [owner, &interface, interfaceName](
1110 const std::shared_ptr<Codec2Client> &client)
1111 -> c2_status_t {
1112 c2_status_t status = client->createInterface(interfaceName,
1113 &interface);
1114 if (status == C2_OK) {
1115 if (owner) {
1116 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001117 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001118 } else if (status != C2_NOT_FOUND) {
1119 LOG(DEBUG) << "IComponentStore("
1120 << client->getServiceName()
1121 << ")::createInterface(\"" << interfaceName
1122 << "\") returned status = "
1123 << status << ".";
1124 }
1125 return status;
1126 });
1127 if (status != C2_OK) {
1128 LOG(DEBUG) << "Failed to create interface \"" << interfaceName
1129 << "\" from all known services. "
1130 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001131 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001132 return interface;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001133}
1134
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001135std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
1136 static std::vector<C2Component::Traits> sList{[]() {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001137 std::vector<C2Component::Traits> list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001138 for (Cache& cache : Cache::List()) {
1139 std::vector<C2Component::Traits> const& traits = cache.getTraits();
1140 list.insert(list.end(), traits.begin(), traits.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001141 }
1142 return list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001143 }()};
1144 return sList;
1145}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001146
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001147std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
1148 char const* serviceName) {
Pawin Vongmasa18588322019-05-18 01:52:13 -07001149 int32_t inputSurfaceSetting = ::android::base::GetIntProperty(
1150 "debug.stagefright.c2inputsurface", int32_t(0));
1151 if (inputSurfaceSetting <= 0) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001152 return nullptr;
1153 }
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001154 size_t index = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001155 if (serviceName) {
1156 index = getServiceIndex(serviceName);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001157 if (index == GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001158 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
1159 << serviceName << "\"";
1160 }
1161 }
1162
1163 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001164 if (index != GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001165 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
1166 if (client->createInputSurface(&inputSurface) == C2_OK) {
1167 return inputSurface;
1168 }
1169 }
1170 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
1171 "from all services...";
1172 for (Cache& cache : Cache::List()) {
1173 std::shared_ptr<Codec2Client> client = cache.getClient();
1174 if (client->createInputSurface(&inputSurface) == C2_OK) {
1175 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
1176 "service \"" << client->getServiceName() << "\"";
1177 return inputSurface;
1178 }
1179 }
1180 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
1181 "from all services";
1182 return nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001183}
1184
1185// Codec2Client::Listener
1186
1187Codec2Client::Listener::~Listener() {
1188}
1189
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001190// Codec2Client::Interface
1191Codec2Client::Interface::Interface(const sp<Base>& base)
1192 : Configurable{
1193 [base]() -> sp<IConfigurable> {
1194 Return<sp<IConfigurable>> transResult =
1195 base->getConfigurable();
1196 return transResult.isOk() ?
1197 static_cast<sp<IConfigurable>>(transResult) :
1198 nullptr;
1199 }()
1200 },
1201 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001202}
1203
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001204// Codec2Client::Component
1205Codec2Client::Component::Component(const sp<Base>& base)
1206 : Configurable{
1207 [base]() -> sp<IConfigurable> {
1208 Return<sp<IComponentInterface>> transResult1 =
1209 base->getInterface();
1210 if (!transResult1.isOk()) {
1211 return nullptr;
1212 }
1213 Return<sp<IConfigurable>> transResult2 =
1214 static_cast<sp<IComponentInterface>>(transResult1)->
1215 getConfigurable();
1216 return transResult2.isOk() ?
1217 static_cast<sp<IConfigurable>>(transResult2) :
1218 nullptr;
1219 }()
1220 },
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001221 mBase1_0{base},
1222 mBase1_1{Base1_1::castFrom(base)},
Sungtak Lee8577dab2021-03-12 02:25:50 -08001223 mBase1_2{Base1_2::castFrom(base)},
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001224 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1225 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1226}
1227
1228Codec2Client::Component::Component(const sp<Base1_1>& base)
1229 : Configurable{
1230 [base]() -> sp<IConfigurable> {
1231 Return<sp<IComponentInterface>> transResult1 =
1232 base->getInterface();
1233 if (!transResult1.isOk()) {
1234 return nullptr;
1235 }
1236 Return<sp<IConfigurable>> transResult2 =
1237 static_cast<sp<IComponentInterface>>(transResult1)->
1238 getConfigurable();
1239 return transResult2.isOk() ?
1240 static_cast<sp<IConfigurable>>(transResult2) :
1241 nullptr;
1242 }()
1243 },
1244 mBase1_0{base},
1245 mBase1_1{base},
Sungtak Lee8577dab2021-03-12 02:25:50 -08001246 mBase1_2{Base1_2::castFrom(base)},
1247 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1248 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1249}
1250
1251Codec2Client::Component::Component(const sp<Base1_2>& base)
1252 : Configurable{
1253 [base]() -> sp<IConfigurable> {
1254 Return<sp<IComponentInterface>> transResult1 =
1255 base->getInterface();
1256 if (!transResult1.isOk()) {
1257 return nullptr;
1258 }
1259 Return<sp<IConfigurable>> transResult2 =
1260 static_cast<sp<IComponentInterface>>(transResult1)->
1261 getConfigurable();
1262 return transResult2.isOk() ?
1263 static_cast<sp<IConfigurable>>(transResult2) :
1264 nullptr;
1265 }()
1266 },
1267 mBase1_0{base},
1268 mBase1_1{base},
1269 mBase1_2{base},
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001270 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1271 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001272}
1273
1274Codec2Client::Component::~Component() {
1275}
1276
1277c2_status_t Codec2Client::Component::createBlockPool(
1278 C2Allocator::id_t id,
1279 C2BlockPool::local_id_t* blockPoolId,
1280 std::shared_ptr<Codec2Client::Configurable>* configurable) {
1281 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001282 Return<void> transStatus = mBase1_0->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001283 static_cast<uint32_t>(id),
1284 [&status, blockPoolId, configurable](
1285 Status s,
1286 uint64_t pId,
1287 const sp<IConfigurable>& c) {
1288 status = static_cast<c2_status_t>(s);
1289 configurable->reset();
1290 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001291 LOG(DEBUG) << "createBlockPool -- call failed: "
1292 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001293 return;
1294 }
1295 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001296 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001297 });
1298 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001299 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001300 return C2_TRANSACTION_FAILED;
1301 }
1302 return status;
1303}
1304
1305c2_status_t Codec2Client::Component::destroyBlockPool(
1306 C2BlockPool::local_id_t localId) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001307 Return<Status> transResult = mBase1_0->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001308 static_cast<uint64_t>(localId));
1309 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001310 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001311 return C2_TRANSACTION_FAILED;
1312 }
1313 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1314}
1315
Wonsik Kimab34ed62019-01-31 15:28:46 -08001316void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001317 const std::list<std::unique_ptr<C2Work>> &workItems) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001318 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001319 mOutputBufferQueue->holdBufferQueueBlocks(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001320}
1321
1322c2_status_t Codec2Client::Component::queue(
1323 std::list<std::unique_ptr<C2Work>>* const items) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001324 WorkBundle workBundle;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001325 if (!objcpy(&workBundle, *items, mBufferPoolSender.get())) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001326 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001327 return C2_TRANSACTION_FAILED;
1328 }
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001329 Return<Status> transStatus = mBase1_0->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001330 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001331 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001332 return C2_TRANSACTION_FAILED;
1333 }
1334 c2_status_t status =
1335 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1336 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001337 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001338 }
1339 return status;
1340}
1341
1342c2_status_t Codec2Client::Component::flush(
1343 C2Component::flush_mode_t mode,
1344 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
1345 (void)mode; // Flush mode isn't supported in HIDL yet.
1346 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001347 Return<void> transStatus = mBase1_0->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001348 [&status, flushedWork](
1349 Status s, const WorkBundle& wb) {
1350 status = static_cast<c2_status_t>(s);
1351 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001352 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001353 return;
1354 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001355 if (!objcpy(flushedWork, wb)) {
1356 status = C2_CORRUPTED;
1357 } else {
1358 status = C2_OK;
1359 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001360 });
1361 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001362 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001363 return C2_TRANSACTION_FAILED;
1364 }
1365
1366 // Indices of flushed work items.
1367 std::vector<uint64_t> flushedIndices;
1368 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
1369 if (work) {
1370 if (work->worklets.empty()
1371 || !work->worklets.back()
1372 || (work->worklets.back()->output.flags &
1373 C2FrameData::FLAG_INCOMPLETE) == 0) {
1374 // input is complete
1375 flushedIndices.emplace_back(
1376 work->input.ordinal.frameIndex.peeku());
1377 }
1378 }
1379 }
1380
Pawin Vongmasa36653902018-11-15 00:10:25 -08001381 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001382 mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001383
1384 return status;
1385}
1386
1387c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001388 Return<Status> transStatus = mBase1_0->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001389 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1390 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001391 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001392 return C2_TRANSACTION_FAILED;
1393 }
1394 c2_status_t status =
1395 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1396 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001397 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001398 }
1399 return status;
1400}
1401
1402c2_status_t Codec2Client::Component::start() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001403 Return<Status> transStatus = mBase1_0->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001404 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001405 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001406 return C2_TRANSACTION_FAILED;
1407 }
1408 c2_status_t status =
1409 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1410 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001411 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001412 }
1413 return status;
1414}
1415
1416c2_status_t Codec2Client::Component::stop() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001417 Return<Status> transStatus = mBase1_0->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001418 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001419 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001420 return C2_TRANSACTION_FAILED;
1421 }
1422 c2_status_t status =
1423 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1424 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001425 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001426 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001427 return status;
1428}
1429
1430c2_status_t Codec2Client::Component::reset() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001431 Return<Status> transStatus = mBase1_0->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001432 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001433 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001434 return C2_TRANSACTION_FAILED;
1435 }
1436 c2_status_t status =
1437 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1438 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001439 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001440 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001441 return status;
1442}
1443
1444c2_status_t Codec2Client::Component::release() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001445 Return<Status> transStatus = mBase1_0->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001446 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001447 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001448 return C2_TRANSACTION_FAILED;
1449 }
1450 c2_status_t status =
1451 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1452 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001453 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001454 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001455 return status;
1456}
1457
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001458c2_status_t Codec2Client::Component::configureVideoTunnel(
1459 uint32_t avSyncHwId,
1460 native_handle_t** sidebandHandle) {
1461 *sidebandHandle = nullptr;
1462 if (!mBase1_1) {
1463 return C2_OMITTED;
1464 }
1465 c2_status_t status{};
1466 Return<void> transStatus = mBase1_1->configureVideoTunnel(avSyncHwId,
1467 [&status, sidebandHandle](
1468 Status s, hardware::hidl_handle const& h) {
1469 status = static_cast<c2_status_t>(s);
1470 if (h.getNativeHandle()) {
1471 *sidebandHandle = native_handle_clone(h.getNativeHandle());
1472 }
1473 });
1474 if (!transStatus.isOk()) {
1475 LOG(ERROR) << "configureVideoTunnel -- transaction failed.";
1476 return C2_TRANSACTION_FAILED;
1477 }
1478 return status;
1479}
1480
Pawin Vongmasa36653902018-11-15 00:10:25 -08001481c2_status_t Codec2Client::Component::setOutputSurface(
1482 C2BlockPool::local_id_t blockPoolId,
1483 const sp<IGraphicBufferProducer>& surface,
1484 uint32_t generation) {
Sungtak Lee08515812019-06-05 11:16:32 -07001485 uint64_t bqId = 0;
1486 sp<IGraphicBufferProducer> nullIgbp;
1487 sp<HGraphicBufferProducer2> nullHgbp;
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08001488
Sungtak Lee08515812019-06-05 11:16:32 -07001489 sp<HGraphicBufferProducer2> igbp = surface ?
1490 surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
1491 if (surface && !igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001492 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001493 }
1494
Sungtak Lee08515812019-06-05 11:16:32 -07001495 if (!surface) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001496 mOutputBufferQueue->configure(nullIgbp, generation, 0);
Sungtak Lee08515812019-06-05 11:16:32 -07001497 } else if (surface->getUniqueId(&bqId) != OK) {
1498 LOG(ERROR) << "setOutputSurface -- "
1499 "cannot obtain bufferqueue id.";
1500 bqId = 0;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001501 mOutputBufferQueue->configure(nullIgbp, generation, 0);
Sungtak Lee08515812019-06-05 11:16:32 -07001502 } else {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001503 mOutputBufferQueue->configure(surface, generation, bqId);
Sungtak Lee08515812019-06-05 11:16:32 -07001504 }
1505 ALOGD("generation remote change %u", generation);
1506
Sungtak Lee8577dab2021-03-12 02:25:50 -08001507 (void)mBase1_2;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001508 Return<Status> transStatus = mBase1_0->setOutputSurface(
Sungtak Lee08515812019-06-05 11:16:32 -07001509 static_cast<uint64_t>(blockPoolId),
1510 bqId == 0 ? nullHgbp : igbp);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001511 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001512 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001513 return C2_TRANSACTION_FAILED;
1514 }
1515 c2_status_t status =
1516 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1517 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001518 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001519 }
1520 return status;
1521}
1522
1523status_t Codec2Client::Component::queueToOutputSurface(
1524 const C2ConstGraphicBlock& block,
1525 const QueueBufferInput& input,
1526 QueueBufferOutput* output) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001527 return mOutputBufferQueue->outputBuffer(block, input, output);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001528}
1529
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001530c2_status_t Codec2Client::Component::connectToInputSurface(
1531 const std::shared_ptr<InputSurface>& inputSurface,
1532 std::shared_ptr<InputSurfaceConnection>* connection) {
1533 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001534 Return<void> transStatus = mBase1_0->connectToInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001535 inputSurface->mBase,
1536 [&status, connection](
1537 Status s, const sp<IInputSurfaceConnection>& c) {
1538 status = static_cast<c2_status_t>(s);
1539 if (status != C2_OK) {
1540 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1541 << status << ".";
1542 return;
1543 }
1544 *connection = std::make_shared<InputSurfaceConnection>(c);
1545 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001546 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001547 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001548 return C2_TRANSACTION_FAILED;
1549 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001550 return status;
1551}
1552
1553c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001554 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001555 const sp<HGraphicBufferSource>& source,
1556 std::shared_ptr<InputSurfaceConnection>* connection) {
1557 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001558 Return<void> transStatus = mBase1_0->connectToOmxInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001559 producer, source,
1560 [&status, connection](
1561 Status s, const sp<IInputSurfaceConnection>& c) {
1562 status = static_cast<c2_status_t>(s);
1563 if (status != C2_OK) {
1564 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1565 << status << ".";
1566 return;
1567 }
1568 *connection = std::make_shared<InputSurfaceConnection>(c);
1569 });
1570 if (!transStatus.isOk()) {
1571 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1572 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001573 }
1574 return status;
1575}
1576
1577c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001578 Return<Status> transStatus = mBase1_0->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001579 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001580 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001581 return C2_TRANSACTION_FAILED;
1582 }
1583 c2_status_t status =
1584 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1585 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001586 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1587 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001588 }
1589 return status;
1590}
1591
1592c2_status_t Codec2Client::Component::setDeathListener(
1593 const std::shared_ptr<Component>& component,
1594 const std::shared_ptr<Listener>& listener) {
1595
1596 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1597 std::weak_ptr<Component> component;
1598 std::weak_ptr<Listener> base;
1599
1600 virtual void serviceDied(
1601 uint64_t /* cookie */,
1602 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1603 ) override {
1604 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1605 listener->onDeath(component);
1606 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001607 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001608 }
1609 }
1610 };
1611
1612 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1613 deathRecipient->base = listener;
1614 deathRecipient->component = component;
1615
1616 component->mDeathRecipient = deathRecipient;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001617 Return<bool> transResult = component->mBase1_0->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001618 component->mDeathRecipient, 0);
1619 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001620 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001621 return C2_TRANSACTION_FAILED;
1622 }
1623 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001624 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001625 return C2_CORRUPTED;
1626 }
1627 return C2_OK;
1628}
1629
1630// Codec2Client::InputSurface
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001631Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base)
1632 : Configurable{
1633 [base]() -> sp<IConfigurable> {
1634 Return<sp<IConfigurable>> transResult =
1635 base->getConfigurable();
1636 return transResult.isOk() ?
1637 static_cast<sp<IConfigurable>>(transResult) :
1638 nullptr;
1639 }()
1640 },
1641 mBase{base},
1642 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001643 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
1644 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001645 base->getGraphicBufferProducer();
1646 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001647 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001648 nullptr;
1649 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001650}
1651
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001652sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08001653 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1654 return mGraphicBufferProducer;
1655}
1656
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001657sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001658 return mBase;
1659}
1660
1661// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08001662Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001663 const sp<IInputSurfaceConnection>& base)
1664 : Configurable{
1665 [base]() -> sp<IConfigurable> {
1666 Return<sp<IConfigurable>> transResult =
1667 base->getConfigurable();
1668 return transResult.isOk() ?
1669 static_cast<sp<IConfigurable>>(transResult) :
1670 nullptr;
1671 }()
1672 },
1673 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001674}
1675
1676c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001677 Return<Status> transResult = mBase->disconnect();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001678 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1679}
1680
1681} // namespace android
1682