blob: 71857e05fa11ddba06b151f45afeeec06f389aed [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>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070036#include <codec2/hidl/1.0/types.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070037#include <codec2/hidl/1.1/types.h>
Sungtak Lee8577dab2021-03-12 02:25:50 -080038#include <codec2/hidl/1.2/types.h>
Sungtak Leea714f112021-03-16 05:40:03 -070039#include <codec2/hidl/output.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070040
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
Sungtak Leea714f112021-03-16 05:40:03 -070046
Pawin Vongmasa36653902018-11-15 00:10:25 -080047#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;
Sungtak Leea714f112021-03-16 05:40:03 -070077using ::android::hardware::media::c2::V1_2::SurfaceSyncObj;
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080078
Pawin Vongmasa36653902018-11-15 00:10:25 -080079namespace /* unnamed */ {
80
81// c2_status_t value that corresponds to hwbinder transaction failure.
82constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
83
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070084// Searches for a name in GetServiceNames() and returns the index found. If the
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070085// name is not found, the returned index will be equal to
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070086// GetServiceNames().size().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070087size_t getServiceIndex(char const* name) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070088 std::vector<std::string> const& names = Codec2Client::GetServiceNames();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070089 size_t i = 0;
90 for (; i < names.size(); ++i) {
91 if (name == names[i]) {
92 break;
93 }
Pawin Vongmasa36653902018-11-15 00:10:25 -080094 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070095 return i;
Pawin Vongmasa36653902018-11-15 00:10:25 -080096}
97
Pawin Vongmasa83d2c552020-03-05 04:36:08 -080098class Client2Store : public C2ComponentStore {
99 std::shared_ptr<Codec2Client> mClient;
100
101public:
102 Client2Store(std::shared_ptr<Codec2Client> const& client)
103 : mClient(client) { }
104
105 virtual ~Client2Store() = default;
106
107 virtual c2_status_t config_sm(
108 std::vector<C2Param*> const &params,
109 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
110 return mClient->config(params, C2_MAY_BLOCK, failures);
111 };
112
113 virtual c2_status_t copyBuffer(
114 std::shared_ptr<C2GraphicBuffer>,
115 std::shared_ptr<C2GraphicBuffer>) {
116 return C2_OMITTED;
117 }
118
119 virtual c2_status_t createComponent(
120 C2String, std::shared_ptr<C2Component>* const component) {
121 component->reset();
122 return C2_OMITTED;
123 }
124
125 virtual c2_status_t createInterface(
126 C2String, std::shared_ptr<C2ComponentInterface>* const interface) {
127 interface->reset();
128 return C2_OMITTED;
129 }
130
131 virtual c2_status_t query_sm(
132 std::vector<C2Param*> const& stackParams,
133 std::vector<C2Param::Index> const& heapParamIndices,
134 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
135 return mClient->query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
136 }
137
138 virtual c2_status_t querySupportedParams_nb(
139 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
140 return mClient->querySupportedParams(params);
141 }
142
143 virtual c2_status_t querySupportedValues_sm(
144 std::vector<C2FieldSupportedValuesQuery>& fields) const {
145 return mClient->querySupportedValues(fields, C2_MAY_BLOCK);
146 }
147
148 virtual C2String getName() const {
149 return mClient->getName();
150 }
151
152 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const {
153 return mClient->getParamReflector();
154 }
155
156 virtual std::vector<std::shared_ptr<C2Component::Traits const>> listComponents() {
157 return std::vector<std::shared_ptr<C2Component::Traits const>>();
158 }
159};
160
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700161} // unnamed namespace
162
163// This class caches a Codec2Client object and its component traits. The client
164// will be created the first time it is needed, and it can be refreshed if the
165// service dies (by calling invalidate()). The first time listComponents() is
166// called from the client, the result will be cached.
167class Codec2Client::Cache {
168 // Cached client
169 std::shared_ptr<Codec2Client> mClient;
170 mutable std::mutex mClientMutex;
171
172 // Cached component traits
173 std::vector<C2Component::Traits> mTraits;
174 std::once_flag mTraitsInitializationFlag;
175
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700176 // The index of the service. This is based on GetServiceNames().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700177 size_t mIndex;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700178 // Called by s() exactly once to initialize the cache. The index must be a
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700179 // valid index into the vector returned by GetServiceNames(). Calling
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700180 // init(index) will associate the cache to the service with name
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700181 // GetServiceNames()[index].
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700182 void init(size_t index) {
183 mIndex = index;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700184 }
185
186public:
187 Cache() = default;
188
189 // Initializes mClient if needed, then returns mClient.
190 // If the service is unavailable but listed in the manifest, this function
191 // will block indefinitely.
192 std::shared_ptr<Codec2Client> getClient() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700193 std::scoped_lock lock{mClientMutex};
194 if (!mClient) {
195 mClient = Codec2Client::_CreateFromIndex(mIndex);
196 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700197 CHECK(mClient) << "Failed to create Codec2Client to service \""
198 << GetServiceNames()[mIndex] << "\". (Index = "
199 << mIndex << ").";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700200 return mClient;
201 }
202
203 // Causes a subsequent call to getClient() to create a new client. This
204 // function should be called after the service dies.
205 //
206 // Note: This function is called only by ForAllServices().
207 void invalidate() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700208 std::scoped_lock lock{mClientMutex};
209 mClient = nullptr;
210 }
211
212 // Returns a list of traits for components supported by the service. This
213 // list is cached.
214 std::vector<C2Component::Traits> const& getTraits() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700215 std::call_once(mTraitsInitializationFlag, [this]() {
216 bool success{false};
217 // Spin until _listComponents() is successful.
218 while (true) {
219 std::shared_ptr<Codec2Client> client = getClient();
220 mTraits = client->_listComponents(&success);
221 if (success) {
222 break;
223 }
Pawin Vongmasa21617db2020-04-24 06:16:42 -0700224 invalidate();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700225 using namespace std::chrono_literals;
226 static constexpr auto kServiceRetryPeriod = 5s;
227 LOG(INFO) << "Failed to retrieve component traits from service "
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700228 "\"" << GetServiceNames()[mIndex] << "\". "
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700229 "Retrying...";
230 std::this_thread::sleep_for(kServiceRetryPeriod);
231 }
232 });
233 return mTraits;
234 }
235
236 // List() returns the list of all caches.
237 static std::vector<Cache>& List() {
238 static std::vector<Cache> sCaches{[]() {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700239 size_t numServices = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700240 std::vector<Cache> caches(numServices);
241 for (size_t i = 0; i < numServices; ++i) {
242 caches[i].init(i);
243 }
244 return caches;
245 }()};
246 return sCaches;
247 }
248};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800249
250// Codec2ConfigurableClient
251
252const C2String& Codec2ConfigurableClient::getName() const {
253 return mName;
254}
255
Pawin Vongmasa36653902018-11-15 00:10:25 -0800256Codec2ConfigurableClient::Codec2ConfigurableClient(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800257 const sp<IConfigurable>& base)
258 : mBase{base},
259 mName{[base]() -> C2String {
260 C2String outName;
261 Return<void> transStatus = base->getName(
262 [&outName](const hidl_string& name) {
263 outName = name.c_str();
264 });
265 return transStatus.isOk() ? outName : "";
266 }()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800267}
268
269c2_status_t Codec2ConfigurableClient::query(
270 const std::vector<C2Param*> &stackParams,
271 const std::vector<C2Param::Index> &heapParamIndices,
272 c2_blocking_t mayBlock,
273 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
274 hidl_vec<ParamIndex> indices(
275 stackParams.size() + heapParamIndices.size());
276 size_t numIndices = 0;
277 for (C2Param* const& stackParam : stackParams) {
278 if (!stackParam) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800279 LOG(WARNING) << "query -- null stack param encountered.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800280 continue;
281 }
282 indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
283 }
284 size_t numStackIndices = numIndices;
285 for (const C2Param::Index& index : heapParamIndices) {
286 indices[numIndices++] =
287 static_cast<ParamIndex>(static_cast<uint32_t>(index));
288 }
289 indices.resize(numIndices);
290 if (heapParams) {
291 heapParams->reserve(heapParams->size() + numIndices);
292 }
293 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800294 Return<void> transStatus = mBase->query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800295 indices,
296 mayBlock == C2_MAY_BLOCK,
297 [&status, &numStackIndices, &stackParams, heapParams](
298 Status s, const Params& p) {
299 status = static_cast<c2_status_t>(s);
300 if (status != C2_OK && status != C2_BAD_INDEX) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800301 LOG(DEBUG) << "query -- call failed: "
302 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800303 return;
304 }
305 std::vector<C2Param*> paramPointers;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800306 if (!parseParamsBlob(&paramPointers, p)) {
307 LOG(ERROR) << "query -- error while parsing params.";
308 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800309 return;
310 }
311 size_t i = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800312 for (auto it = paramPointers.begin();
313 it != paramPointers.end(); ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800314 C2Param* paramPointer = *it;
315 if (numStackIndices > 0) {
316 --numStackIndices;
317 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800318 LOG(WARNING) << "query -- null stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800319 ++it;
320 continue;
321 }
322 for (; i < stackParams.size() && !stackParams[i]; ) {
323 ++i;
324 }
325 if (i >= stackParams.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800326 LOG(ERROR) << "query -- unexpected error.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800327 status = C2_CORRUPTED;
328 return;
329 }
330 if (stackParams[i]->index() != paramPointer->index()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800331 LOG(WARNING) << "query -- param skipped: "
332 "index = "
333 << stackParams[i]->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800334 stackParams[i++]->invalidate();
335 continue;
336 }
337 if (!stackParams[i++]->updateFrom(*paramPointer)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800338 LOG(WARNING) << "query -- param update failed: "
339 "index = "
340 << paramPointer->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800341 }
342 } else {
343 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800344 LOG(WARNING) << "query -- null heap param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800345 ++it;
346 continue;
347 }
348 if (!heapParams) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800349 LOG(WARNING) << "query -- "
350 "unexpected extra stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800351 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800352 heapParams->emplace_back(
353 C2Param::Copy(*paramPointer));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800354 }
355 }
356 ++it;
357 }
358 });
359 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800360 LOG(ERROR) << "query -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800361 return C2_TRANSACTION_FAILED;
362 }
363 return status;
364}
365
366c2_status_t Codec2ConfigurableClient::config(
367 const std::vector<C2Param*> &params,
368 c2_blocking_t mayBlock,
369 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
370 Params hidlParams;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800371 if (!createParamsBlob(&hidlParams, params)) {
372 LOG(ERROR) << "config -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800373 return C2_TRANSACTION_FAILED;
374 }
375 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800376 Return<void> transStatus = mBase->config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800377 hidlParams,
378 mayBlock == C2_MAY_BLOCK,
379 [&status, &params, failures](
380 Status s,
381 const hidl_vec<SettingResult> f,
382 const Params& o) {
383 status = static_cast<c2_status_t>(s);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800384 if (status != C2_OK && status != C2_BAD_INDEX) {
385 LOG(DEBUG) << "config -- call failed: "
386 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800387 }
388 size_t i = failures->size();
389 failures->resize(i + f.size());
390 for (const SettingResult& sf : f) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800391 if (!objcpy(&(*failures)[i++], sf)) {
392 LOG(ERROR) << "config -- "
393 << "invalid SettingResult returned.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800394 return;
395 }
396 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800397 if (!updateParamsFromBlob(params, o)) {
398 LOG(ERROR) << "config -- "
399 << "failed to parse returned params.";
400 status = C2_CORRUPTED;
401 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800402 });
403 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800404 LOG(ERROR) << "config -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800405 return C2_TRANSACTION_FAILED;
406 }
407 return status;
408}
409
410c2_status_t Codec2ConfigurableClient::querySupportedParams(
411 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
412 // TODO: Cache and query properly!
413 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800414 Return<void> transStatus = mBase->querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800415 std::numeric_limits<uint32_t>::min(),
416 std::numeric_limits<uint32_t>::max(),
417 [&status, params](
418 Status s,
419 const hidl_vec<ParamDescriptor>& p) {
420 status = static_cast<c2_status_t>(s);
421 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800422 LOG(DEBUG) << "querySupportedParams -- call failed: "
423 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800424 return;
425 }
426 size_t i = params->size();
427 params->resize(i + p.size());
428 for (const ParamDescriptor& sp : p) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800429 if (!objcpy(&(*params)[i++], sp)) {
430 LOG(ERROR) << "querySupportedParams -- "
431 << "invalid returned ParamDescriptor.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800432 return;
433 }
434 }
435 });
436 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800437 LOG(ERROR) << "querySupportedParams -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800438 return C2_TRANSACTION_FAILED;
439 }
440 return status;
441}
442
443c2_status_t Codec2ConfigurableClient::querySupportedValues(
444 std::vector<C2FieldSupportedValuesQuery>& fields,
445 c2_blocking_t mayBlock) const {
446 hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
447 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800448 if (!objcpy(&inFields[i], fields[i])) {
449 LOG(ERROR) << "querySupportedValues -- bad input";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800450 return C2_TRANSACTION_FAILED;
451 }
452 }
453
454 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800455 Return<void> transStatus = mBase->querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800456 inFields,
457 mayBlock == C2_MAY_BLOCK,
458 [&status, &inFields, &fields](
459 Status s,
460 const hidl_vec<FieldSupportedValuesQueryResult>& r) {
461 status = static_cast<c2_status_t>(s);
462 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800463 LOG(DEBUG) << "querySupportedValues -- call failed: "
464 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800465 return;
466 }
467 if (r.size() != fields.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800468 LOG(ERROR) << "querySupportedValues -- "
469 "input and output lists "
470 "have different sizes.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800471 status = C2_CORRUPTED;
472 return;
473 }
474 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800475 if (!objcpy(&fields[i], inFields[i], r[i])) {
476 LOG(ERROR) << "querySupportedValues -- "
477 "invalid returned value.";
478 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800479 return;
480 }
481 }
482 });
483 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800484 LOG(ERROR) << "querySupportedValues -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800485 return C2_TRANSACTION_FAILED;
486 }
487 return status;
488}
489
490// Codec2Client::Component::HidlListener
491struct Codec2Client::Component::HidlListener : public IComponentListener {
492 std::weak_ptr<Component> component;
493 std::weak_ptr<Listener> base;
494
495 virtual Return<void> onWorkDone(const WorkBundle& workBundle) override {
496 std::list<std::unique_ptr<C2Work>> workItems;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800497 if (!objcpy(&workItems, workBundle)) {
498 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800499 return Void();
500 }
501 // release input buffers potentially held by the component from queue
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800502 std::shared_ptr<Codec2Client::Component> strongComponent =
503 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800504 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800505 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800506 }
507 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800508 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800509 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800510 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800511 }
512 return Void();
513 }
514
515 virtual Return<void> onTripped(
516 const hidl_vec<SettingResult>& settingResults) override {
517 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
518 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800519 for (size_t i = 0; i < settingResults.size(); ++i) {
520 std::unique_ptr<C2SettingResult> c2SettingResult;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800521 if (!objcpy(&c2SettingResult, settingResults[i])) {
522 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800523 return Void();
524 }
525 c2SettingResults[i] = std::move(c2SettingResult);
526 }
527 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
528 listener->onTripped(component, c2SettingResults);
529 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800530 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800531 }
532 return Void();
533 }
534
535 virtual Return<void> onError(Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800536 LOG(DEBUG) << "onError --"
537 << " status = " << s
538 << ", errorCode = " << errorCode
539 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800540 if (std::shared_ptr<Listener> listener = base.lock()) {
541 listener->onError(component, s == Status::OK ?
542 errorCode : static_cast<c2_status_t>(s));
543 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800544 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800545 }
546 return Void();
547 }
548
549 virtual Return<void> onFramesRendered(
550 const hidl_vec<RenderedFrame>& renderedFrames) override {
551 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800552 if (!listener) {
553 LOG(DEBUG) << "onFramesRendered -- listener died.";
554 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800555 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800556 for (const RenderedFrame& renderedFrame : renderedFrames) {
557 listener->onFrameRendered(
558 renderedFrame.bufferQueueId,
559 renderedFrame.slotId,
560 renderedFrame.timestampNs);
561 }
562 return Void();
563 }
564
565 virtual Return<void> onInputBuffersReleased(
566 const hidl_vec<InputBuffer>& inputBuffers) override {
567 std::shared_ptr<Listener> listener = base.lock();
568 if (!listener) {
569 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
570 return Void();
571 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800572 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800573 LOG(VERBOSE) << "onInputBuffersReleased --"
574 " received death notification of"
575 " input buffer:"
576 " frameIndex = " << inputBuffer.frameIndex
577 << ", bufferIndex = " << inputBuffer.arrayIndex
578 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -0800579 listener->onInputBufferDone(
580 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800581 }
582 return Void();
583 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800584
Pawin Vongmasa36653902018-11-15 00:10:25 -0800585};
586
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700587// Codec2Client::Component::BufferPoolSender
588struct Codec2Client::Component::BufferPoolSender :
589 hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
590 BufferPoolSender()
591 : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
592 }
593};
594
595// Codec2Client::Component::OutputBufferQueue
596struct Codec2Client::Component::OutputBufferQueue :
Sungtak Leea714f112021-03-16 05:40:03 -0700597 hardware::media::c2::OutputBufferQueue {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700598 OutputBufferQueue()
Sungtak Leea714f112021-03-16 05:40:03 -0700599 : hardware::media::c2::OutputBufferQueue() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700600 }
601};
602
Pawin Vongmasa36653902018-11-15 00:10:25 -0800603// Codec2Client
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700604Codec2Client::Codec2Client(sp<Base> const& base,
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700605 size_t serviceIndex)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800606 : Configurable{
607 [base]() -> sp<IConfigurable> {
608 Return<sp<IConfigurable>> transResult =
609 base->getConfigurable();
610 return transResult.isOk() ?
611 static_cast<sp<IConfigurable>>(transResult) :
612 nullptr;
613 }()
614 },
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700615 mBase1_0{base},
616 mBase1_1{Base1_1::castFrom(base)},
Sungtak Lee8577dab2021-03-12 02:25:50 -0800617 mBase1_2{Base1_2::castFrom(base)},
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700618 mServiceIndex{serviceIndex} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800619 Return<sp<IClientManager>> transResult = base->getPoolClientManager();
620 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800621 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800622 } else {
623 mHostPoolManager = static_cast<sp<IClientManager>>(transResult);
624 }
625}
626
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700627sp<Codec2Client::Base> const& Codec2Client::getBase() const {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700628 return mBase1_0;
629}
630
631sp<Codec2Client::Base1_0> const& Codec2Client::getBase1_0() const {
632 return mBase1_0;
633}
634
635sp<Codec2Client::Base1_1> const& Codec2Client::getBase1_1() const {
636 return mBase1_1;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700637}
638
Sungtak Lee8577dab2021-03-12 02:25:50 -0800639sp<Codec2Client::Base1_2> const& Codec2Client::getBase1_2() const {
640 return mBase1_2;
641}
642
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700643std::string const& Codec2Client::getServiceName() const {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700644 return GetServiceNames()[mServiceIndex];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700645}
646
Pawin Vongmasa36653902018-11-15 00:10:25 -0800647c2_status_t Codec2Client::createComponent(
648 const C2String& name,
649 const std::shared_ptr<Codec2Client::Listener>& listener,
650 std::shared_ptr<Codec2Client::Component>* const component) {
651
Pawin Vongmasa36653902018-11-15 00:10:25 -0800652 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800653 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800654 hidlListener->base = listener;
Sungtak Lee8577dab2021-03-12 02:25:50 -0800655 Return<void> transStatus;
656 if (mBase1_2) {
657 transStatus = mBase1_2->createComponent_1_2(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800658 name,
659 hidlListener,
660 ClientManager::getInstance(),
661 [&status, component, hidlListener](
662 Status s,
663 const sp<IComponent>& c) {
664 status = static_cast<c2_status_t>(s);
665 if (status != C2_OK) {
666 return;
667 }
668 *component = std::make_shared<Codec2Client::Component>(c);
669 hidlListener->component = *component;
Sungtak Lee8577dab2021-03-12 02:25:50 -0800670 });
671 }
672 else if (mBase1_1) {
673 transStatus = mBase1_1->createComponent_1_1(
674 name,
675 hidlListener,
676 ClientManager::getInstance(),
677 [&status, component, hidlListener](
678 Status s,
679 const sp<IComponent>& c) {
680 status = static_cast<c2_status_t>(s);
681 if (status != C2_OK) {
682 return;
683 }
684 *component = std::make_shared<Codec2Client::Component>(c);
685 hidlListener->component = *component;
686 });
687 } else if (mBase1_0) { // ver1_0
688 transStatus = mBase1_0->createComponent(
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700689 name,
690 hidlListener,
691 ClientManager::getInstance(),
692 [&status, component, hidlListener](
693 Status s,
694 const sp<hardware::media::c2::V1_0::IComponent>& c) {
695 status = static_cast<c2_status_t>(s);
696 if (status != C2_OK) {
697 return;
698 }
699 *component = std::make_shared<Codec2Client::Component>(c);
700 hidlListener->component = *component;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800701 });
Sungtak Lee8577dab2021-03-12 02:25:50 -0800702 } else {
703 status = C2_CORRUPTED;
704 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800705 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800706 LOG(ERROR) << "createComponent(" << name.c_str()
707 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800708 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800709 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800710 if (status == C2_NOT_FOUND) {
711 LOG(VERBOSE) << "createComponent(" << name.c_str()
712 << ") -- component not found.";
713 } else {
714 LOG(ERROR) << "createComponent(" << name.c_str()
715 << ") -- call failed: " << status << ".";
716 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800717 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800718 } else if (!*component) {
719 LOG(ERROR) << "createComponent(" << name.c_str()
720 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800721 return C2_CORRUPTED;
722 }
723
724 status = (*component)->setDeathListener(*component, listener);
725 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800726 LOG(ERROR) << "createComponent(" << name.c_str()
727 << ") -- failed to set up death listener: "
728 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800729 }
730
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700731 (*component)->mBufferPoolSender->setReceiver(mHostPoolManager);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800732 return status;
733}
734
735c2_status_t Codec2Client::createInterface(
736 const C2String& name,
737 std::shared_ptr<Codec2Client::Interface>* const interface) {
738 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700739 Return<void> transStatus = mBase1_0->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800740 name,
741 [&status, interface](
742 Status s,
743 const sp<IComponentInterface>& i) {
744 status = static_cast<c2_status_t>(s);
745 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800746 return;
747 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800748 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800749 });
750 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800751 LOG(ERROR) << "createInterface(" << name.c_str()
752 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800753 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800754 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800755 if (status == C2_NOT_FOUND) {
756 LOG(VERBOSE) << "createInterface(" << name.c_str()
757 << ") -- component not found.";
758 } else {
759 LOG(ERROR) << "createInterface(" << name.c_str()
760 << ") -- call failed: " << status << ".";
761 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800762 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800763 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800764
Pawin Vongmasa36653902018-11-15 00:10:25 -0800765 return status;
766}
767
768c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800769 std::shared_ptr<InputSurface>* const inputSurface) {
770 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700771 Return<void> transStatus = mBase1_0->createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800772 [&status, inputSurface](
773 Status s,
774 const sp<IInputSurface>& i) {
775 status = static_cast<c2_status_t>(s);
776 if (status != C2_OK) {
777 return;
778 }
779 *inputSurface = std::make_shared<InputSurface>(i);
780 });
781 if (!transStatus.isOk()) {
782 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800783 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800784 } else if (status != C2_OK) {
785 LOG(DEBUG) << "createInputSurface -- call failed: "
786 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800787 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800788 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800789}
790
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700791std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
792 return Cache::List()[mServiceIndex].getTraits();
793}
794
795std::vector<C2Component::Traits> Codec2Client::_listComponents(
796 bool* success) const {
797 std::vector<C2Component::Traits> traits;
798 std::string const& serviceName = getServiceName();
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700799 Return<void> transStatus = mBase1_0->listComponents(
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700800 [&traits, &serviceName](Status s,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800801 const hidl_vec<IComponentStore::ComponentTraits>& t) {
802 if (s != Status::OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700803 LOG(DEBUG) << "_listComponents -- call failed: "
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800804 << static_cast<c2_status_t>(s) << ".";
805 return;
806 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700807 traits.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800808 for (size_t i = 0; i < t.size(); ++i) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700809 if (!objcpy(&traits[i], t[i])) {
810 LOG(ERROR) << "_listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800811 return;
812 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700813 traits[i].owner = serviceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800814 }
815 });
816 if (!transStatus.isOk()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700817 LOG(ERROR) << "_listComponents -- transaction failed.";
818 *success = false;
819 } else {
820 *success = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800821 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700822 return traits;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800823}
824
825c2_status_t Codec2Client::copyBuffer(
826 const std::shared_ptr<C2Buffer>& src,
827 const std::shared_ptr<C2Buffer>& dst) {
828 // TODO: Implement?
829 (void)src;
830 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800831 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800832 return C2_OMITTED;
833}
834
835std::shared_ptr<C2ParamReflector>
836 Codec2Client::getParamReflector() {
837 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
838 // should reflect the HAL API.
839 struct SimpleParamReflector : public C2ParamReflector {
840 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
841 hidl_vec<ParamIndex> indices(1);
842 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
843 std::unique_ptr<C2StructDescriptor> descriptor;
844 Return<void> transStatus = mBase->getStructDescriptors(
845 indices,
846 [&descriptor](
847 Status s,
848 const hidl_vec<StructDescriptor>& sd) {
849 c2_status_t status = static_cast<c2_status_t>(s);
850 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800851 LOG(DEBUG) << "SimpleParamReflector -- "
852 "getStructDescriptors() failed: "
853 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800854 descriptor.reset();
855 return;
856 }
857 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800858 LOG(DEBUG) << "SimpleParamReflector -- "
859 "getStructDescriptors() "
860 "returned vector of size "
861 << sd.size() << ". "
862 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800863 descriptor.reset();
864 return;
865 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800866 if (!objcpy(&descriptor, sd[0])) {
867 LOG(DEBUG) << "SimpleParamReflector -- "
868 "getStructDescriptors() returned "
869 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800870 descriptor.reset();
871 return;
872 }
873 });
Wonsik Kim492fecd2020-11-19 11:14:11 -0800874 if (!transStatus.isOk()) {
875 LOG(DEBUG) << "SimpleParamReflector -- transaction failed: "
876 << transStatus.description();
877 descriptor.reset();
878 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800879 return descriptor;
880 }
881
882 SimpleParamReflector(sp<Base> base)
883 : mBase(base) { }
884
885 sp<Base> mBase;
886 };
887
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700888 return std::make_shared<SimpleParamReflector>(mBase1_0);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800889};
890
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700891std::vector<std::string> const& Codec2Client::GetServiceNames() {
892 static std::vector<std::string> sServiceNames{[]() {
893 using ::android::hardware::media::c2::V1_0::IComponentStore;
894 using ::android::hidl::manager::V1_2::IServiceManager;
895
896 while (true) {
897 sp<IServiceManager> serviceManager = IServiceManager::getService();
898 CHECK(serviceManager) << "Hardware service manager is not running.";
899
900 // There are three categories of services based on names.
901 std::vector<std::string> defaultNames; // Prefixed with "default"
902 std::vector<std::string> vendorNames; // Prefixed with "vendor"
903 std::vector<std::string> otherNames; // Others
904 Return<void> transResult;
905 transResult = serviceManager->listManifestByInterface(
906 IComponentStore::descriptor,
907 [&defaultNames, &vendorNames, &otherNames](
908 hidl_vec<hidl_string> const& instanceNames) {
909 for (hidl_string const& instanceName : instanceNames) {
910 char const* name = instanceName.c_str();
911 if (strncmp(name, "default", 7) == 0) {
912 defaultNames.emplace_back(name);
913 } else if (strncmp(name, "vendor", 6) == 0) {
914 vendorNames.emplace_back(name);
915 } else {
916 otherNames.emplace_back(name);
917 }
918 }
919 });
920 if (transResult.isOk()) {
921 // Sort service names in each category.
922 std::sort(defaultNames.begin(), defaultNames.end());
923 std::sort(vendorNames.begin(), vendorNames.end());
924 std::sort(otherNames.begin(), otherNames.end());
925
926 // Concatenate the three lists in this order: default, vendor,
927 // other.
928 std::vector<std::string>& names = defaultNames;
929 names.reserve(names.size() + vendorNames.size() + otherNames.size());
930 names.insert(names.end(),
931 std::make_move_iterator(vendorNames.begin()),
932 std::make_move_iterator(vendorNames.end()));
933 names.insert(names.end(),
934 std::make_move_iterator(otherNames.begin()),
935 std::make_move_iterator(otherNames.end()));
936
937 // Summarize to logcat.
938 if (names.empty()) {
939 LOG(INFO) << "No Codec2 services declared in the manifest.";
940 } else {
941 std::stringstream stringOutput;
942 stringOutput << "Available Codec2 services:";
943 for (std::string const& name : names) {
944 stringOutput << " \"" << name << "\"";
945 }
946 LOG(INFO) << stringOutput.str();
947 }
948
949 return names;
950 }
951 LOG(ERROR) << "Could not retrieve the list of service instances of "
952 << IComponentStore::descriptor
953 << ". Retrying...";
954 }
955 }()};
956 return sServiceNames;
957}
958
Pawin Vongmasa36653902018-11-15 00:10:25 -0800959std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa83d2c552020-03-05 04:36:08 -0800960 const char* name,
961 bool setAsPreferredCodec2ComponentStore) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700962 size_t index = getServiceIndex(name);
Pawin Vongmasa83d2c552020-03-05 04:36:08 -0800963 if (index == GetServiceNames().size()) {
964 if (setAsPreferredCodec2ComponentStore) {
965 LOG(WARNING) << "CreateFromService(" << name
966 << ") -- preferred C2ComponentStore not set.";
967 }
968 return nullptr;
969 }
970 std::shared_ptr<Codec2Client> client = _CreateFromIndex(index);
971 if (setAsPreferredCodec2ComponentStore) {
972 SetPreferredCodec2ComponentStore(
973 std::make_shared<Client2Store>(client));
974 LOG(INFO) << "CreateFromService(" << name
975 << ") -- service set as preferred C2ComponentStore.";
976 }
977 return client;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800978}
979
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700980std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
981 CreateFromAllServices() {
982 std::vector<std::shared_ptr<Codec2Client>> clients(
983 GetServiceNames().size());
984 for (size_t i = GetServiceNames().size(); i > 0; ) {
985 --i;
986 clients[i] = _CreateFromIndex(i);
987 }
988 return clients;
989}
990
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700991std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700992 std::string const& name = GetServiceNames()[index];
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800993 LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700994 sp<Base> baseStore = Base::getService(name);
995 CHECK(baseStore) << "Codec2 service \"" << name << "\""
996 " inaccessible for unknown reasons.";
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800997 LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700998 return std::make_shared<Codec2Client>(baseStore, index);
999}
1000
1001c2_status_t Codec2Client::ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001002 const std::string &key,
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001003 size_t numberOfAttempts,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001004 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
1005 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001006 c2_status_t status = C2_NO_INIT; // no IComponentStores present
1007
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001008 // Cache the mapping key -> index of Codec2Client in Cache::List().
Pawin Vongmasa36653902018-11-15 00:10:25 -08001009 static std::mutex key2IndexMutex;
1010 static std::map<std::string, size_t> key2Index;
1011
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001012 // By default try all stores. However, try the last known client first. If
1013 // the last known client fails, retry once. We do this by pushing the last
1014 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -08001015 std::deque<size_t> indices;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001016 for (size_t index = Cache::List().size(); index > 0; ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001017 indices.push_front(--index);
1018 }
1019
1020 bool wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001021 {
1022 std::scoped_lock lock{key2IndexMutex};
1023 auto it = key2Index.find(key);
1024 if (it != key2Index.end()) {
1025 indices.push_front(it->second);
1026 wasMapped = true;
1027 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001028 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001029
1030 for (size_t index : indices) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001031 Cache& cache = Cache::List()[index];
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001032 for (size_t tries = numberOfAttempts; tries > 0; --tries) {
1033 std::shared_ptr<Codec2Client> client{cache.getClient()};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001034 status = predicate(client);
1035 if (status == C2_OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001036 std::scoped_lock lock{key2IndexMutex};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001037 key2Index[key] = index; // update last known client index
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001038 return C2_OK;
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001039 } else if (status == C2_NO_MEMORY) {
1040 return C2_NO_MEMORY;
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001041 } else if (status == C2_TRANSACTION_FAILED) {
1042 LOG(WARNING) << "\"" << key << "\" failed for service \""
1043 << client->getName()
1044 << "\" due to transaction failure. "
1045 << "(Service may have crashed.)"
1046 << (tries > 1 ? " Retrying..." : "");
1047 cache.invalidate();
1048 continue;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001049 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001050 if (wasMapped) {
1051 LOG(INFO) << "\"" << key << "\" became invalid in service \""
1052 << client->getName() << "\". Retrying...";
1053 wasMapped = false;
1054 }
1055 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001056 }
1057 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001058 return status; // return the last status from a valid client
Pawin Vongmasa36653902018-11-15 00:10:25 -08001059}
1060
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001061c2_status_t Codec2Client::CreateComponentByName(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001062 const char* componentName,
1063 const std::shared_ptr<Listener>& listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001064 std::shared_ptr<Component>* component,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001065 std::shared_ptr<Codec2Client>* owner,
1066 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001067 std::string key{"create:"};
1068 key.append(componentName);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001069 c2_status_t status = ForAllServices(
1070 key,
1071 numberOfAttempts,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001072 [owner, component, componentName, &listener](
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001073 const std::shared_ptr<Codec2Client> &client)
1074 -> c2_status_t {
1075 c2_status_t status = client->createComponent(componentName,
1076 listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001077 component);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001078 if (status == C2_OK) {
1079 if (owner) {
1080 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001081 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001082 } else if (status != C2_NOT_FOUND) {
1083 LOG(DEBUG) << "IComponentStore("
1084 << client->getServiceName()
1085 << ")::createComponent(\"" << componentName
1086 << "\") returned status = "
1087 << status << ".";
1088 }
1089 return status;
1090 });
1091 if (status != C2_OK) {
1092 LOG(DEBUG) << "Failed to create component \"" << componentName
1093 << "\" from all known services. "
1094 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001095 }
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001096 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001097}
1098
1099std::shared_ptr<Codec2Client::Interface>
1100 Codec2Client::CreateInterfaceByName(
1101 const char* interfaceName,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001102 std::shared_ptr<Codec2Client>* owner,
1103 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001104 std::string key{"create:"};
1105 key.append(interfaceName);
1106 std::shared_ptr<Interface> interface;
1107 c2_status_t status = ForAllServices(
1108 key,
1109 numberOfAttempts,
1110 [owner, &interface, interfaceName](
1111 const std::shared_ptr<Codec2Client> &client)
1112 -> c2_status_t {
1113 c2_status_t status = client->createInterface(interfaceName,
1114 &interface);
1115 if (status == C2_OK) {
1116 if (owner) {
1117 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001118 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001119 } else if (status != C2_NOT_FOUND) {
1120 LOG(DEBUG) << "IComponentStore("
1121 << client->getServiceName()
1122 << ")::createInterface(\"" << interfaceName
1123 << "\") returned status = "
1124 << status << ".";
1125 }
1126 return status;
1127 });
1128 if (status != C2_OK) {
1129 LOG(DEBUG) << "Failed to create interface \"" << interfaceName
1130 << "\" from all known services. "
1131 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001132 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001133 return interface;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001134}
1135
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001136std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
1137 static std::vector<C2Component::Traits> sList{[]() {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001138 std::vector<C2Component::Traits> list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001139 for (Cache& cache : Cache::List()) {
1140 std::vector<C2Component::Traits> const& traits = cache.getTraits();
1141 list.insert(list.end(), traits.begin(), traits.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001142 }
1143 return list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001144 }()};
1145 return sList;
1146}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001147
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001148std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
1149 char const* serviceName) {
Pawin Vongmasa18588322019-05-18 01:52:13 -07001150 int32_t inputSurfaceSetting = ::android::base::GetIntProperty(
1151 "debug.stagefright.c2inputsurface", int32_t(0));
1152 if (inputSurfaceSetting <= 0) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001153 return nullptr;
1154 }
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001155 size_t index = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001156 if (serviceName) {
1157 index = getServiceIndex(serviceName);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001158 if (index == GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001159 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
1160 << serviceName << "\"";
1161 }
1162 }
1163
1164 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001165 if (index != GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001166 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
1167 if (client->createInputSurface(&inputSurface) == C2_OK) {
1168 return inputSurface;
1169 }
1170 }
1171 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
1172 "from all services...";
1173 for (Cache& cache : Cache::List()) {
1174 std::shared_ptr<Codec2Client> client = cache.getClient();
1175 if (client->createInputSurface(&inputSurface) == C2_OK) {
1176 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
1177 "service \"" << client->getServiceName() << "\"";
1178 return inputSurface;
1179 }
1180 }
1181 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
1182 "from all services";
1183 return nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001184}
1185
1186// Codec2Client::Listener
1187
1188Codec2Client::Listener::~Listener() {
1189}
1190
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001191// Codec2Client::Interface
1192Codec2Client::Interface::Interface(const sp<Base>& base)
1193 : Configurable{
1194 [base]() -> sp<IConfigurable> {
1195 Return<sp<IConfigurable>> transResult =
1196 base->getConfigurable();
1197 return transResult.isOk() ?
1198 static_cast<sp<IConfigurable>>(transResult) :
1199 nullptr;
1200 }()
1201 },
1202 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001203}
1204
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001205// Codec2Client::Component
1206Codec2Client::Component::Component(const sp<Base>& base)
1207 : Configurable{
1208 [base]() -> sp<IConfigurable> {
1209 Return<sp<IComponentInterface>> transResult1 =
1210 base->getInterface();
1211 if (!transResult1.isOk()) {
1212 return nullptr;
1213 }
1214 Return<sp<IConfigurable>> transResult2 =
1215 static_cast<sp<IComponentInterface>>(transResult1)->
1216 getConfigurable();
1217 return transResult2.isOk() ?
1218 static_cast<sp<IConfigurable>>(transResult2) :
1219 nullptr;
1220 }()
1221 },
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001222 mBase1_0{base},
1223 mBase1_1{Base1_1::castFrom(base)},
Sungtak Lee8577dab2021-03-12 02:25:50 -08001224 mBase1_2{Base1_2::castFrom(base)},
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001225 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1226 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1227}
1228
1229Codec2Client::Component::Component(const sp<Base1_1>& base)
1230 : Configurable{
1231 [base]() -> sp<IConfigurable> {
1232 Return<sp<IComponentInterface>> transResult1 =
1233 base->getInterface();
1234 if (!transResult1.isOk()) {
1235 return nullptr;
1236 }
1237 Return<sp<IConfigurable>> transResult2 =
1238 static_cast<sp<IComponentInterface>>(transResult1)->
1239 getConfigurable();
1240 return transResult2.isOk() ?
1241 static_cast<sp<IConfigurable>>(transResult2) :
1242 nullptr;
1243 }()
1244 },
1245 mBase1_0{base},
1246 mBase1_1{base},
Sungtak Lee8577dab2021-03-12 02:25:50 -08001247 mBase1_2{Base1_2::castFrom(base)},
1248 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1249 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1250}
1251
1252Codec2Client::Component::Component(const sp<Base1_2>& base)
1253 : Configurable{
1254 [base]() -> sp<IConfigurable> {
1255 Return<sp<IComponentInterface>> transResult1 =
1256 base->getInterface();
1257 if (!transResult1.isOk()) {
1258 return nullptr;
1259 }
1260 Return<sp<IConfigurable>> transResult2 =
1261 static_cast<sp<IComponentInterface>>(transResult1)->
1262 getConfigurable();
1263 return transResult2.isOk() ?
1264 static_cast<sp<IConfigurable>>(transResult2) :
1265 nullptr;
1266 }()
1267 },
1268 mBase1_0{base},
1269 mBase1_1{base},
1270 mBase1_2{base},
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001271 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1272 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001273}
1274
1275Codec2Client::Component::~Component() {
1276}
1277
1278c2_status_t Codec2Client::Component::createBlockPool(
1279 C2Allocator::id_t id,
1280 C2BlockPool::local_id_t* blockPoolId,
1281 std::shared_ptr<Codec2Client::Configurable>* configurable) {
1282 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001283 Return<void> transStatus = mBase1_0->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001284 static_cast<uint32_t>(id),
1285 [&status, blockPoolId, configurable](
1286 Status s,
1287 uint64_t pId,
1288 const sp<IConfigurable>& c) {
1289 status = static_cast<c2_status_t>(s);
1290 configurable->reset();
1291 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001292 LOG(DEBUG) << "createBlockPool -- call failed: "
1293 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001294 return;
1295 }
1296 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001297 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001298 });
1299 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001300 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001301 return C2_TRANSACTION_FAILED;
1302 }
1303 return status;
1304}
1305
1306c2_status_t Codec2Client::Component::destroyBlockPool(
1307 C2BlockPool::local_id_t localId) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001308 Return<Status> transResult = mBase1_0->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001309 static_cast<uint64_t>(localId));
1310 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001311 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001312 return C2_TRANSACTION_FAILED;
1313 }
1314 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1315}
1316
Wonsik Kimab34ed62019-01-31 15:28:46 -08001317void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001318 const std::list<std::unique_ptr<C2Work>> &workItems) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001319 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001320 mOutputBufferQueue->holdBufferQueueBlocks(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001321}
1322
1323c2_status_t Codec2Client::Component::queue(
1324 std::list<std::unique_ptr<C2Work>>* const items) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001325 WorkBundle workBundle;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001326 if (!objcpy(&workBundle, *items, mBufferPoolSender.get())) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001327 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001328 return C2_TRANSACTION_FAILED;
1329 }
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001330 Return<Status> transStatus = mBase1_0->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001331 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001332 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001333 return C2_TRANSACTION_FAILED;
1334 }
1335 c2_status_t status =
1336 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1337 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001338 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001339 }
1340 return status;
1341}
1342
1343c2_status_t Codec2Client::Component::flush(
1344 C2Component::flush_mode_t mode,
1345 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
1346 (void)mode; // Flush mode isn't supported in HIDL yet.
1347 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001348 Return<void> transStatus = mBase1_0->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001349 [&status, flushedWork](
1350 Status s, const WorkBundle& wb) {
1351 status = static_cast<c2_status_t>(s);
1352 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001353 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001354 return;
1355 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001356 if (!objcpy(flushedWork, wb)) {
1357 status = C2_CORRUPTED;
1358 } else {
1359 status = C2_OK;
1360 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001361 });
1362 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001363 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001364 return C2_TRANSACTION_FAILED;
1365 }
1366
1367 // Indices of flushed work items.
1368 std::vector<uint64_t> flushedIndices;
1369 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
1370 if (work) {
1371 if (work->worklets.empty()
1372 || !work->worklets.back()
1373 || (work->worklets.back()->output.flags &
1374 C2FrameData::FLAG_INCOMPLETE) == 0) {
1375 // input is complete
1376 flushedIndices.emplace_back(
1377 work->input.ordinal.frameIndex.peeku());
1378 }
1379 }
1380 }
1381
Pawin Vongmasa36653902018-11-15 00:10:25 -08001382 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001383 mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001384
1385 return status;
1386}
1387
1388c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001389 Return<Status> transStatus = mBase1_0->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001390 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1391 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001392 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001393 return C2_TRANSACTION_FAILED;
1394 }
1395 c2_status_t status =
1396 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1397 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001398 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001399 }
1400 return status;
1401}
1402
1403c2_status_t Codec2Client::Component::start() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001404 Return<Status> transStatus = mBase1_0->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001405 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001406 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001407 return C2_TRANSACTION_FAILED;
1408 }
1409 c2_status_t status =
1410 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1411 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001412 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001413 }
1414 return status;
1415}
1416
1417c2_status_t Codec2Client::Component::stop() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001418 Return<Status> transStatus = mBase1_0->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001419 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001420 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001421 return C2_TRANSACTION_FAILED;
1422 }
1423 c2_status_t status =
1424 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1425 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001426 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001427 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001428 return status;
1429}
1430
1431c2_status_t Codec2Client::Component::reset() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001432 Return<Status> transStatus = mBase1_0->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001433 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001434 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001435 return C2_TRANSACTION_FAILED;
1436 }
1437 c2_status_t status =
1438 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1439 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001440 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001441 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001442 return status;
1443}
1444
1445c2_status_t Codec2Client::Component::release() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001446 Return<Status> transStatus = mBase1_0->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001447 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001448 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001449 return C2_TRANSACTION_FAILED;
1450 }
1451 c2_status_t status =
1452 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1453 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001454 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001455 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001456 return status;
1457}
1458
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001459c2_status_t Codec2Client::Component::configureVideoTunnel(
1460 uint32_t avSyncHwId,
1461 native_handle_t** sidebandHandle) {
1462 *sidebandHandle = nullptr;
1463 if (!mBase1_1) {
1464 return C2_OMITTED;
1465 }
1466 c2_status_t status{};
1467 Return<void> transStatus = mBase1_1->configureVideoTunnel(avSyncHwId,
1468 [&status, sidebandHandle](
1469 Status s, hardware::hidl_handle const& h) {
1470 status = static_cast<c2_status_t>(s);
1471 if (h.getNativeHandle()) {
1472 *sidebandHandle = native_handle_clone(h.getNativeHandle());
1473 }
1474 });
1475 if (!transStatus.isOk()) {
1476 LOG(ERROR) << "configureVideoTunnel -- transaction failed.";
1477 return C2_TRANSACTION_FAILED;
1478 }
1479 return status;
1480}
1481
Pawin Vongmasa36653902018-11-15 00:10:25 -08001482c2_status_t Codec2Client::Component::setOutputSurface(
1483 C2BlockPool::local_id_t blockPoolId,
1484 const sp<IGraphicBufferProducer>& surface,
Sungtak Leedb14cba2021-04-10 00:50:23 -07001485 uint32_t generation,
1486 int maxDequeueCount) {
Sungtak Lee08515812019-06-05 11:16:32 -07001487 uint64_t bqId = 0;
1488 sp<IGraphicBufferProducer> nullIgbp;
1489 sp<HGraphicBufferProducer2> nullHgbp;
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08001490
Sungtak Lee08515812019-06-05 11:16:32 -07001491 sp<HGraphicBufferProducer2> igbp = surface ?
1492 surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
1493 if (surface && !igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001494 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001495 }
1496
Sungtak Leea714f112021-03-16 05:40:03 -07001497 std::shared_ptr<SurfaceSyncObj> syncObj;
1498
Sungtak Lee08515812019-06-05 11:16:32 -07001499 if (!surface) {
Sungtak Leedb14cba2021-04-10 00:50:23 -07001500 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07001501 } else if (surface->getUniqueId(&bqId) != OK) {
1502 LOG(ERROR) << "setOutputSurface -- "
1503 "cannot obtain bufferqueue id.";
1504 bqId = 0;
Sungtak Leedb14cba2021-04-10 00:50:23 -07001505 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07001506 } else {
Sungtak Leedb14cba2021-04-10 00:50:23 -07001507 mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount, mBase1_2 ?
1508 &syncObj : nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07001509 }
Sungtak Leea714f112021-03-16 05:40:03 -07001510 ALOGD("surface generation remote change %u HAL ver: %s",
1511 generation, syncObj ? "1.2" : "1.0");
Sungtak Lee08515812019-06-05 11:16:32 -07001512
Sungtak Leea714f112021-03-16 05:40:03 -07001513 Return<Status> transStatus = syncObj ?
1514 mBase1_2->setOutputSurfaceWithSyncObj(
1515 static_cast<uint64_t>(blockPoolId),
1516 bqId == 0 ? nullHgbp : igbp, *syncObj) :
1517 mBase1_0->setOutputSurface(
1518 static_cast<uint64_t>(blockPoolId),
1519 bqId == 0 ? nullHgbp : igbp);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001520 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001521 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001522 return C2_TRANSACTION_FAILED;
1523 }
1524 c2_status_t status =
1525 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1526 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001527 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001528 }
Sungtak Leea714f112021-03-16 05:40:03 -07001529 ALOGD("Surface configure completed");
Pawin Vongmasa36653902018-11-15 00:10:25 -08001530 return status;
1531}
1532
1533status_t Codec2Client::Component::queueToOutputSurface(
1534 const C2ConstGraphicBlock& block,
1535 const QueueBufferInput& input,
1536 QueueBufferOutput* output) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001537 return mOutputBufferQueue->outputBuffer(block, input, output);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001538}
1539
Sungtak Leea714f112021-03-16 05:40:03 -07001540void Codec2Client::Component::setOutputSurfaceMaxDequeueCount(
1541 int maxDequeueCount) {
1542 mOutputBufferQueue->updateMaxDequeueBufferCount(maxDequeueCount);
1543}
1544
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001545c2_status_t Codec2Client::Component::connectToInputSurface(
1546 const std::shared_ptr<InputSurface>& inputSurface,
1547 std::shared_ptr<InputSurfaceConnection>* connection) {
1548 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001549 Return<void> transStatus = mBase1_0->connectToInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001550 inputSurface->mBase,
1551 [&status, connection](
1552 Status s, const sp<IInputSurfaceConnection>& c) {
1553 status = static_cast<c2_status_t>(s);
1554 if (status != C2_OK) {
1555 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1556 << status << ".";
1557 return;
1558 }
1559 *connection = std::make_shared<InputSurfaceConnection>(c);
1560 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001561 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001562 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001563 return C2_TRANSACTION_FAILED;
1564 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001565 return status;
1566}
1567
1568c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001569 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001570 const sp<HGraphicBufferSource>& source,
1571 std::shared_ptr<InputSurfaceConnection>* connection) {
1572 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001573 Return<void> transStatus = mBase1_0->connectToOmxInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001574 producer, source,
1575 [&status, connection](
1576 Status s, const sp<IInputSurfaceConnection>& c) {
1577 status = static_cast<c2_status_t>(s);
1578 if (status != C2_OK) {
1579 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1580 << status << ".";
1581 return;
1582 }
1583 *connection = std::make_shared<InputSurfaceConnection>(c);
1584 });
1585 if (!transStatus.isOk()) {
1586 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1587 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001588 }
1589 return status;
1590}
1591
1592c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001593 Return<Status> transStatus = mBase1_0->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001594 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001595 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001596 return C2_TRANSACTION_FAILED;
1597 }
1598 c2_status_t status =
1599 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1600 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001601 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1602 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001603 }
1604 return status;
1605}
1606
1607c2_status_t Codec2Client::Component::setDeathListener(
1608 const std::shared_ptr<Component>& component,
1609 const std::shared_ptr<Listener>& listener) {
1610
1611 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1612 std::weak_ptr<Component> component;
1613 std::weak_ptr<Listener> base;
1614
1615 virtual void serviceDied(
1616 uint64_t /* cookie */,
1617 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1618 ) override {
1619 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1620 listener->onDeath(component);
1621 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001622 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001623 }
1624 }
1625 };
1626
1627 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1628 deathRecipient->base = listener;
1629 deathRecipient->component = component;
1630
1631 component->mDeathRecipient = deathRecipient;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001632 Return<bool> transResult = component->mBase1_0->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001633 component->mDeathRecipient, 0);
1634 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001635 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001636 return C2_TRANSACTION_FAILED;
1637 }
1638 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001639 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001640 return C2_CORRUPTED;
1641 }
1642 return C2_OK;
1643}
1644
1645// Codec2Client::InputSurface
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001646Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base)
1647 : Configurable{
1648 [base]() -> sp<IConfigurable> {
1649 Return<sp<IConfigurable>> transResult =
1650 base->getConfigurable();
1651 return transResult.isOk() ?
1652 static_cast<sp<IConfigurable>>(transResult) :
1653 nullptr;
1654 }()
1655 },
1656 mBase{base},
1657 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001658 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
1659 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001660 base->getGraphicBufferProducer();
1661 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001662 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001663 nullptr;
1664 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001665}
1666
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001667sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08001668 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1669 return mGraphicBufferProducer;
1670}
1671
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001672sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001673 return mBase;
1674}
1675
1676// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08001677Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001678 const sp<IInputSurfaceConnection>& base)
1679 : Configurable{
1680 [base]() -> sp<IConfigurable> {
1681 Return<sp<IConfigurable>> transResult =
1682 base->getConfigurable();
1683 return transResult.isOk() ?
1684 static_cast<sp<IConfigurable>>(transResult) :
1685 nullptr;
1686 }()
1687 },
1688 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001689}
1690
1691c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001692 Return<Status> transResult = mBase->disconnect();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001693 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1694}
1695
1696} // namespace android
1697