blob: 0acab495aa2c59bc535e1c1f27f23348eb45142e [file] [log] [blame]
Pawin Vongmasa36653902018-11-15 00:10:25 -08001/*
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002 * Copyright 2018 The Android Open Source Project
Pawin Vongmasa36653902018-11-15 00:10:25 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "Codec2Client"
Pawin Vongmasa1c75a232019-01-09 04:41:52 -080019#include <android-base/logging.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080020
21#include <codec2/hidl/client.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070022#include <C2Debug.h>
23#include <C2BufferPriv.h>
24#include <C2PlatformSupport.h>
25
26#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
27#include <android/hardware/media/c2/1.0/IComponent.h>
28#include <android/hardware/media/c2/1.0/IComponentInterface.h>
29#include <android/hardware/media/c2/1.0/IComponentListener.h>
30#include <android/hardware/media/c2/1.0/IComponentStore.h>
31#include <android/hardware/media/c2/1.0/IConfigurable.h>
32#include <android/hidl/manager/1.2/IServiceManager.h>
33
34#include <android-base/properties.h>
35#include <bufferpool/ClientManager.h>
36#include <codec2/hidl/1.0/OutputBufferQueue.h>
37#include <codec2/hidl/1.0/types.h>
38#include <codec2/hidl/1.1/OutputBufferQueue.h>
39#include <codec2/hidl/1.1/types.h>
40
41#include <cutils/native_handle.h>
42#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
43#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
44#include <hidl/HidlSupport.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080045
46#include <deque>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070047#include <iterator>
Pawin Vongmasa36653902018-11-15 00:10:25 -080048#include <limits>
49#include <map>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070050#include <mutex>
51#include <sstream>
52#include <thread>
Pawin Vongmasa36653902018-11-15 00:10:25 -080053#include <type_traits>
54#include <vector>
55
Pawin Vongmasa36653902018-11-15 00:10:25 -080056namespace android {
57
58using ::android::hardware::hidl_vec;
59using ::android::hardware::hidl_string;
60using ::android::hardware::Return;
61using ::android::hardware::Void;
Pawin Vongmasa36653902018-11-15 00:10:25 -080062
Pawin Vongmasabf69de92019-10-29 06:21:27 -070063using namespace ::android::hardware::media::c2::V1_1;
64using namespace ::android::hardware::media::c2::V1_1::utils;
Sungtak Leed3318082018-09-07 15:52:43 -070065using namespace ::android::hardware::media::bufferpool::V2_0;
66using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
Pawin Vongmasa36653902018-11-15 00:10:25 -080067
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080068using HGraphicBufferProducer1 = ::android::hardware::graphics::bufferqueue::
69 V1_0::IGraphicBufferProducer;
70using HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
71 V2_0::IGraphicBufferProducer;
72using B2HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
73 V2_0::utils::B2HGraphicBufferProducer;
74using H2BGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
75 V2_0::utils::H2BGraphicBufferProducer;
76
Pawin Vongmasa36653902018-11-15 00:10:25 -080077namespace /* unnamed */ {
78
79// c2_status_t value that corresponds to hwbinder transaction failure.
80constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
81
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070082// Searches for a name in GetServiceNames() and returns the index found. If the
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070083// name is not found, the returned index will be equal to
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070084// GetServiceNames().size().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070085size_t getServiceIndex(char const* name) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070086 std::vector<std::string> const& names = Codec2Client::GetServiceNames();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070087 size_t i = 0;
88 for (; i < names.size(); ++i) {
89 if (name == names[i]) {
90 break;
91 }
Pawin Vongmasa36653902018-11-15 00:10:25 -080092 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070093 return i;
Pawin Vongmasa36653902018-11-15 00:10:25 -080094}
95
Pawin Vongmasa83d2c552020-03-05 04:36:08 -080096class Client2Store : public C2ComponentStore {
97 std::shared_ptr<Codec2Client> mClient;
98
99public:
100 Client2Store(std::shared_ptr<Codec2Client> const& client)
101 : mClient(client) { }
102
103 virtual ~Client2Store() = default;
104
105 virtual c2_status_t config_sm(
106 std::vector<C2Param*> const &params,
107 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
108 return mClient->config(params, C2_MAY_BLOCK, failures);
109 };
110
111 virtual c2_status_t copyBuffer(
112 std::shared_ptr<C2GraphicBuffer>,
113 std::shared_ptr<C2GraphicBuffer>) {
114 return C2_OMITTED;
115 }
116
117 virtual c2_status_t createComponent(
118 C2String, std::shared_ptr<C2Component>* const component) {
119 component->reset();
120 return C2_OMITTED;
121 }
122
123 virtual c2_status_t createInterface(
124 C2String, std::shared_ptr<C2ComponentInterface>* const interface) {
125 interface->reset();
126 return C2_OMITTED;
127 }
128
129 virtual c2_status_t query_sm(
130 std::vector<C2Param*> const& stackParams,
131 std::vector<C2Param::Index> const& heapParamIndices,
132 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
133 return mClient->query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
134 }
135
136 virtual c2_status_t querySupportedParams_nb(
137 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
138 return mClient->querySupportedParams(params);
139 }
140
141 virtual c2_status_t querySupportedValues_sm(
142 std::vector<C2FieldSupportedValuesQuery>& fields) const {
143 return mClient->querySupportedValues(fields, C2_MAY_BLOCK);
144 }
145
146 virtual C2String getName() const {
147 return mClient->getName();
148 }
149
150 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const {
151 return mClient->getParamReflector();
152 }
153
154 virtual std::vector<std::shared_ptr<C2Component::Traits const>> listComponents() {
155 return std::vector<std::shared_ptr<C2Component::Traits const>>();
156 }
157};
158
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700159} // unnamed namespace
160
161// This class caches a Codec2Client object and its component traits. The client
162// will be created the first time it is needed, and it can be refreshed if the
163// service dies (by calling invalidate()). The first time listComponents() is
164// called from the client, the result will be cached.
165class Codec2Client::Cache {
166 // Cached client
167 std::shared_ptr<Codec2Client> mClient;
168 mutable std::mutex mClientMutex;
169
170 // Cached component traits
171 std::vector<C2Component::Traits> mTraits;
172 std::once_flag mTraitsInitializationFlag;
173
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700174 // The index of the service. This is based on GetServiceNames().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700175 size_t mIndex;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700176 // Called by s() exactly once to initialize the cache. The index must be a
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700177 // valid index into the vector returned by GetServiceNames(). Calling
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700178 // init(index) will associate the cache to the service with name
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700179 // GetServiceNames()[index].
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700180 void init(size_t index) {
181 mIndex = index;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700182 }
183
184public:
185 Cache() = default;
186
187 // Initializes mClient if needed, then returns mClient.
188 // If the service is unavailable but listed in the manifest, this function
189 // will block indefinitely.
190 std::shared_ptr<Codec2Client> getClient() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700191 std::scoped_lock lock{mClientMutex};
192 if (!mClient) {
193 mClient = Codec2Client::_CreateFromIndex(mIndex);
194 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700195 CHECK(mClient) << "Failed to create Codec2Client to service \""
196 << GetServiceNames()[mIndex] << "\". (Index = "
197 << mIndex << ").";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700198 return mClient;
199 }
200
201 // Causes a subsequent call to getClient() to create a new client. This
202 // function should be called after the service dies.
203 //
204 // Note: This function is called only by ForAllServices().
205 void invalidate() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700206 std::scoped_lock lock{mClientMutex};
207 mClient = nullptr;
208 }
209
210 // Returns a list of traits for components supported by the service. This
211 // list is cached.
212 std::vector<C2Component::Traits> const& getTraits() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700213 std::call_once(mTraitsInitializationFlag, [this]() {
214 bool success{false};
215 // Spin until _listComponents() is successful.
216 while (true) {
217 std::shared_ptr<Codec2Client> client = getClient();
218 mTraits = client->_listComponents(&success);
219 if (success) {
220 break;
221 }
222 using namespace std::chrono_literals;
223 static constexpr auto kServiceRetryPeriod = 5s;
224 LOG(INFO) << "Failed to retrieve component traits from service "
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700225 "\"" << GetServiceNames()[mIndex] << "\". "
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700226 "Retrying...";
227 std::this_thread::sleep_for(kServiceRetryPeriod);
228 }
229 });
230 return mTraits;
231 }
232
233 // List() returns the list of all caches.
234 static std::vector<Cache>& List() {
235 static std::vector<Cache> sCaches{[]() {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700236 size_t numServices = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700237 std::vector<Cache> caches(numServices);
238 for (size_t i = 0; i < numServices; ++i) {
239 caches[i].init(i);
240 }
241 return caches;
242 }()};
243 return sCaches;
244 }
245};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800246
247// Codec2ConfigurableClient
248
249const C2String& Codec2ConfigurableClient::getName() const {
250 return mName;
251}
252
Pawin Vongmasa36653902018-11-15 00:10:25 -0800253Codec2ConfigurableClient::Codec2ConfigurableClient(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800254 const sp<IConfigurable>& base)
255 : mBase{base},
256 mName{[base]() -> C2String {
257 C2String outName;
258 Return<void> transStatus = base->getName(
259 [&outName](const hidl_string& name) {
260 outName = name.c_str();
261 });
262 return transStatus.isOk() ? outName : "";
263 }()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800264}
265
266c2_status_t Codec2ConfigurableClient::query(
267 const std::vector<C2Param*> &stackParams,
268 const std::vector<C2Param::Index> &heapParamIndices,
269 c2_blocking_t mayBlock,
270 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
271 hidl_vec<ParamIndex> indices(
272 stackParams.size() + heapParamIndices.size());
273 size_t numIndices = 0;
274 for (C2Param* const& stackParam : stackParams) {
275 if (!stackParam) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800276 LOG(WARNING) << "query -- null stack param encountered.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800277 continue;
278 }
279 indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
280 }
281 size_t numStackIndices = numIndices;
282 for (const C2Param::Index& index : heapParamIndices) {
283 indices[numIndices++] =
284 static_cast<ParamIndex>(static_cast<uint32_t>(index));
285 }
286 indices.resize(numIndices);
287 if (heapParams) {
288 heapParams->reserve(heapParams->size() + numIndices);
289 }
290 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800291 Return<void> transStatus = mBase->query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800292 indices,
293 mayBlock == C2_MAY_BLOCK,
294 [&status, &numStackIndices, &stackParams, heapParams](
295 Status s, const Params& p) {
296 status = static_cast<c2_status_t>(s);
297 if (status != C2_OK && status != C2_BAD_INDEX) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800298 LOG(DEBUG) << "query -- call failed: "
299 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800300 return;
301 }
302 std::vector<C2Param*> paramPointers;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800303 if (!parseParamsBlob(&paramPointers, p)) {
304 LOG(ERROR) << "query -- error while parsing params.";
305 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800306 return;
307 }
308 size_t i = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800309 for (auto it = paramPointers.begin();
310 it != paramPointers.end(); ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800311 C2Param* paramPointer = *it;
312 if (numStackIndices > 0) {
313 --numStackIndices;
314 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800315 LOG(WARNING) << "query -- null stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800316 ++it;
317 continue;
318 }
319 for (; i < stackParams.size() && !stackParams[i]; ) {
320 ++i;
321 }
322 if (i >= stackParams.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800323 LOG(ERROR) << "query -- unexpected error.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800324 status = C2_CORRUPTED;
325 return;
326 }
327 if (stackParams[i]->index() != paramPointer->index()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800328 LOG(WARNING) << "query -- param skipped: "
329 "index = "
330 << stackParams[i]->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800331 stackParams[i++]->invalidate();
332 continue;
333 }
334 if (!stackParams[i++]->updateFrom(*paramPointer)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800335 LOG(WARNING) << "query -- param update failed: "
336 "index = "
337 << paramPointer->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800338 }
339 } else {
340 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800341 LOG(WARNING) << "query -- null heap param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800342 ++it;
343 continue;
344 }
345 if (!heapParams) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800346 LOG(WARNING) << "query -- "
347 "unexpected extra stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800348 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800349 heapParams->emplace_back(
350 C2Param::Copy(*paramPointer));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800351 }
352 }
353 ++it;
354 }
355 });
356 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800357 LOG(ERROR) << "query -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800358 return C2_TRANSACTION_FAILED;
359 }
360 return status;
361}
362
363c2_status_t Codec2ConfigurableClient::config(
364 const std::vector<C2Param*> &params,
365 c2_blocking_t mayBlock,
366 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
367 Params hidlParams;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800368 if (!createParamsBlob(&hidlParams, params)) {
369 LOG(ERROR) << "config -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800370 return C2_TRANSACTION_FAILED;
371 }
372 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800373 Return<void> transStatus = mBase->config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800374 hidlParams,
375 mayBlock == C2_MAY_BLOCK,
376 [&status, &params, failures](
377 Status s,
378 const hidl_vec<SettingResult> f,
379 const Params& o) {
380 status = static_cast<c2_status_t>(s);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800381 if (status != C2_OK && status != C2_BAD_INDEX) {
382 LOG(DEBUG) << "config -- call failed: "
383 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800384 }
385 size_t i = failures->size();
386 failures->resize(i + f.size());
387 for (const SettingResult& sf : f) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800388 if (!objcpy(&(*failures)[i++], sf)) {
389 LOG(ERROR) << "config -- "
390 << "invalid SettingResult returned.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800391 return;
392 }
393 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800394 if (!updateParamsFromBlob(params, o)) {
395 LOG(ERROR) << "config -- "
396 << "failed to parse returned params.";
397 status = C2_CORRUPTED;
398 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800399 });
400 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800401 LOG(ERROR) << "config -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800402 return C2_TRANSACTION_FAILED;
403 }
404 return status;
405}
406
407c2_status_t Codec2ConfigurableClient::querySupportedParams(
408 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
409 // TODO: Cache and query properly!
410 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800411 Return<void> transStatus = mBase->querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800412 std::numeric_limits<uint32_t>::min(),
413 std::numeric_limits<uint32_t>::max(),
414 [&status, params](
415 Status s,
416 const hidl_vec<ParamDescriptor>& p) {
417 status = static_cast<c2_status_t>(s);
418 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800419 LOG(DEBUG) << "querySupportedParams -- call failed: "
420 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800421 return;
422 }
423 size_t i = params->size();
424 params->resize(i + p.size());
425 for (const ParamDescriptor& sp : p) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800426 if (!objcpy(&(*params)[i++], sp)) {
427 LOG(ERROR) << "querySupportedParams -- "
428 << "invalid returned ParamDescriptor.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800429 return;
430 }
431 }
432 });
433 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800434 LOG(ERROR) << "querySupportedParams -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800435 return C2_TRANSACTION_FAILED;
436 }
437 return status;
438}
439
440c2_status_t Codec2ConfigurableClient::querySupportedValues(
441 std::vector<C2FieldSupportedValuesQuery>& fields,
442 c2_blocking_t mayBlock) const {
443 hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
444 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800445 if (!objcpy(&inFields[i], fields[i])) {
446 LOG(ERROR) << "querySupportedValues -- bad input";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800447 return C2_TRANSACTION_FAILED;
448 }
449 }
450
451 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800452 Return<void> transStatus = mBase->querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800453 inFields,
454 mayBlock == C2_MAY_BLOCK,
455 [&status, &inFields, &fields](
456 Status s,
457 const hidl_vec<FieldSupportedValuesQueryResult>& r) {
458 status = static_cast<c2_status_t>(s);
459 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800460 LOG(DEBUG) << "querySupportedValues -- call failed: "
461 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800462 return;
463 }
464 if (r.size() != fields.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800465 LOG(ERROR) << "querySupportedValues -- "
466 "input and output lists "
467 "have different sizes.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800468 status = C2_CORRUPTED;
469 return;
470 }
471 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800472 if (!objcpy(&fields[i], inFields[i], r[i])) {
473 LOG(ERROR) << "querySupportedValues -- "
474 "invalid returned value.";
475 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800476 return;
477 }
478 }
479 });
480 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800481 LOG(ERROR) << "querySupportedValues -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800482 return C2_TRANSACTION_FAILED;
483 }
484 return status;
485}
486
487// Codec2Client::Component::HidlListener
488struct Codec2Client::Component::HidlListener : public IComponentListener {
489 std::weak_ptr<Component> component;
490 std::weak_ptr<Listener> base;
491
492 virtual Return<void> onWorkDone(const WorkBundle& workBundle) override {
493 std::list<std::unique_ptr<C2Work>> workItems;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800494 if (!objcpy(&workItems, workBundle)) {
495 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800496 return Void();
497 }
498 // release input buffers potentially held by the component from queue
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800499 std::shared_ptr<Codec2Client::Component> strongComponent =
500 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800501 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800502 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800503 }
504 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800505 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800506 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800507 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800508 }
509 return Void();
510 }
511
512 virtual Return<void> onTripped(
513 const hidl_vec<SettingResult>& settingResults) override {
514 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
515 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800516 for (size_t i = 0; i < settingResults.size(); ++i) {
517 std::unique_ptr<C2SettingResult> c2SettingResult;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800518 if (!objcpy(&c2SettingResult, settingResults[i])) {
519 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800520 return Void();
521 }
522 c2SettingResults[i] = std::move(c2SettingResult);
523 }
524 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
525 listener->onTripped(component, c2SettingResults);
526 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800527 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800528 }
529 return Void();
530 }
531
532 virtual Return<void> onError(Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800533 LOG(DEBUG) << "onError --"
534 << " status = " << s
535 << ", errorCode = " << errorCode
536 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800537 if (std::shared_ptr<Listener> listener = base.lock()) {
538 listener->onError(component, s == Status::OK ?
539 errorCode : static_cast<c2_status_t>(s));
540 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800541 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800542 }
543 return Void();
544 }
545
546 virtual Return<void> onFramesRendered(
547 const hidl_vec<RenderedFrame>& renderedFrames) override {
548 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800549 if (!listener) {
550 LOG(DEBUG) << "onFramesRendered -- listener died.";
551 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800552 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800553 for (const RenderedFrame& renderedFrame : renderedFrames) {
554 listener->onFrameRendered(
555 renderedFrame.bufferQueueId,
556 renderedFrame.slotId,
557 renderedFrame.timestampNs);
558 }
559 return Void();
560 }
561
562 virtual Return<void> onInputBuffersReleased(
563 const hidl_vec<InputBuffer>& inputBuffers) override {
564 std::shared_ptr<Listener> listener = base.lock();
565 if (!listener) {
566 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
567 return Void();
568 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800569 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800570 LOG(VERBOSE) << "onInputBuffersReleased --"
571 " received death notification of"
572 " input buffer:"
573 " frameIndex = " << inputBuffer.frameIndex
574 << ", bufferIndex = " << inputBuffer.arrayIndex
575 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -0800576 listener->onInputBufferDone(
577 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800578 }
579 return Void();
580 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800581
Pawin Vongmasa36653902018-11-15 00:10:25 -0800582};
583
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700584// Codec2Client::Component::BufferPoolSender
585struct Codec2Client::Component::BufferPoolSender :
586 hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
587 BufferPoolSender()
588 : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
589 }
590};
591
592// Codec2Client::Component::OutputBufferQueue
593struct Codec2Client::Component::OutputBufferQueue :
594 hardware::media::c2::V1_1::utils::OutputBufferQueue {
595 OutputBufferQueue()
596 : hardware::media::c2::V1_1::utils::OutputBufferQueue() {
597 }
598};
599
Pawin Vongmasa36653902018-11-15 00:10:25 -0800600// Codec2Client
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700601Codec2Client::Codec2Client(sp<Base> const& base,
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700602 size_t serviceIndex)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800603 : Configurable{
604 [base]() -> sp<IConfigurable> {
605 Return<sp<IConfigurable>> transResult =
606 base->getConfigurable();
607 return transResult.isOk() ?
608 static_cast<sp<IConfigurable>>(transResult) :
609 nullptr;
610 }()
611 },
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700612 mBase1_0{base},
613 mBase1_1{Base1_1::castFrom(base)},
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700614 mServiceIndex{serviceIndex} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800615 Return<sp<IClientManager>> transResult = base->getPoolClientManager();
616 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800617 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800618 } else {
619 mHostPoolManager = static_cast<sp<IClientManager>>(transResult);
620 }
621}
622
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700623sp<Codec2Client::Base> const& Codec2Client::getBase() const {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700624 return mBase1_0;
625}
626
627sp<Codec2Client::Base1_0> const& Codec2Client::getBase1_0() const {
628 return mBase1_0;
629}
630
631sp<Codec2Client::Base1_1> const& Codec2Client::getBase1_1() const {
632 return mBase1_1;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700633}
634
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700635std::string const& Codec2Client::getServiceName() const {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700636 return GetServiceNames()[mServiceIndex];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700637}
638
Pawin Vongmasa36653902018-11-15 00:10:25 -0800639c2_status_t Codec2Client::createComponent(
640 const C2String& name,
641 const std::shared_ptr<Codec2Client::Listener>& listener,
642 std::shared_ptr<Codec2Client::Component>* const component) {
643
Pawin Vongmasa36653902018-11-15 00:10:25 -0800644 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800645 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800646 hidlListener->base = listener;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700647 Return<void> transStatus = mBase1_1 ?
648 mBase1_1->createComponent_1_1(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800649 name,
650 hidlListener,
651 ClientManager::getInstance(),
652 [&status, component, hidlListener](
653 Status s,
654 const sp<IComponent>& c) {
655 status = static_cast<c2_status_t>(s);
656 if (status != C2_OK) {
657 return;
658 }
659 *component = std::make_shared<Codec2Client::Component>(c);
660 hidlListener->component = *component;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700661 }) :
662 mBase1_0->createComponent(
663 name,
664 hidlListener,
665 ClientManager::getInstance(),
666 [&status, component, hidlListener](
667 Status s,
668 const sp<hardware::media::c2::V1_0::IComponent>& c) {
669 status = static_cast<c2_status_t>(s);
670 if (status != C2_OK) {
671 return;
672 }
673 *component = std::make_shared<Codec2Client::Component>(c);
674 hidlListener->component = *component;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800675 });
676 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800677 LOG(ERROR) << "createComponent(" << name.c_str()
678 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800679 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800680 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800681 if (status == C2_NOT_FOUND) {
682 LOG(VERBOSE) << "createComponent(" << name.c_str()
683 << ") -- component not found.";
684 } else {
685 LOG(ERROR) << "createComponent(" << name.c_str()
686 << ") -- call failed: " << status << ".";
687 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800688 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800689 } else if (!*component) {
690 LOG(ERROR) << "createComponent(" << name.c_str()
691 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800692 return C2_CORRUPTED;
693 }
694
695 status = (*component)->setDeathListener(*component, listener);
696 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800697 LOG(ERROR) << "createComponent(" << name.c_str()
698 << ") -- failed to set up death listener: "
699 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800700 }
701
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700702 (*component)->mBufferPoolSender->setReceiver(mHostPoolManager);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800703 return status;
704}
705
706c2_status_t Codec2Client::createInterface(
707 const C2String& name,
708 std::shared_ptr<Codec2Client::Interface>* const interface) {
709 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700710 Return<void> transStatus = mBase1_0->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800711 name,
712 [&status, interface](
713 Status s,
714 const sp<IComponentInterface>& i) {
715 status = static_cast<c2_status_t>(s);
716 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800717 return;
718 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800719 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800720 });
721 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800722 LOG(ERROR) << "createInterface(" << name.c_str()
723 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800724 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800725 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800726 if (status == C2_NOT_FOUND) {
727 LOG(VERBOSE) << "createInterface(" << name.c_str()
728 << ") -- component not found.";
729 } else {
730 LOG(ERROR) << "createInterface(" << name.c_str()
731 << ") -- call failed: " << status << ".";
732 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800733 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800734 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800735
Pawin Vongmasa36653902018-11-15 00:10:25 -0800736 return status;
737}
738
739c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800740 std::shared_ptr<InputSurface>* const inputSurface) {
741 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700742 Return<void> transStatus = mBase1_0->createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800743 [&status, inputSurface](
744 Status s,
745 const sp<IInputSurface>& i) {
746 status = static_cast<c2_status_t>(s);
747 if (status != C2_OK) {
748 return;
749 }
750 *inputSurface = std::make_shared<InputSurface>(i);
751 });
752 if (!transStatus.isOk()) {
753 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800754 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800755 } else if (status != C2_OK) {
756 LOG(DEBUG) << "createInputSurface -- call failed: "
757 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800758 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800759 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800760}
761
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700762std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
763 return Cache::List()[mServiceIndex].getTraits();
764}
765
766std::vector<C2Component::Traits> Codec2Client::_listComponents(
767 bool* success) const {
768 std::vector<C2Component::Traits> traits;
769 std::string const& serviceName = getServiceName();
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700770 Return<void> transStatus = mBase1_0->listComponents(
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700771 [&traits, &serviceName](Status s,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800772 const hidl_vec<IComponentStore::ComponentTraits>& t) {
773 if (s != Status::OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700774 LOG(DEBUG) << "_listComponents -- call failed: "
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800775 << static_cast<c2_status_t>(s) << ".";
776 return;
777 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700778 traits.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800779 for (size_t i = 0; i < t.size(); ++i) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700780 if (!objcpy(&traits[i], t[i])) {
781 LOG(ERROR) << "_listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800782 return;
783 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700784 traits[i].owner = serviceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800785 }
786 });
787 if (!transStatus.isOk()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700788 LOG(ERROR) << "_listComponents -- transaction failed.";
789 *success = false;
790 } else {
791 *success = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800792 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700793 return traits;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800794}
795
796c2_status_t Codec2Client::copyBuffer(
797 const std::shared_ptr<C2Buffer>& src,
798 const std::shared_ptr<C2Buffer>& dst) {
799 // TODO: Implement?
800 (void)src;
801 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800802 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800803 return C2_OMITTED;
804}
805
806std::shared_ptr<C2ParamReflector>
807 Codec2Client::getParamReflector() {
808 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
809 // should reflect the HAL API.
810 struct SimpleParamReflector : public C2ParamReflector {
811 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
812 hidl_vec<ParamIndex> indices(1);
813 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
814 std::unique_ptr<C2StructDescriptor> descriptor;
815 Return<void> transStatus = mBase->getStructDescriptors(
816 indices,
817 [&descriptor](
818 Status s,
819 const hidl_vec<StructDescriptor>& sd) {
820 c2_status_t status = static_cast<c2_status_t>(s);
821 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800822 LOG(DEBUG) << "SimpleParamReflector -- "
823 "getStructDescriptors() failed: "
824 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800825 descriptor.reset();
826 return;
827 }
828 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800829 LOG(DEBUG) << "SimpleParamReflector -- "
830 "getStructDescriptors() "
831 "returned vector of size "
832 << sd.size() << ". "
833 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800834 descriptor.reset();
835 return;
836 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800837 if (!objcpy(&descriptor, sd[0])) {
838 LOG(DEBUG) << "SimpleParamReflector -- "
839 "getStructDescriptors() returned "
840 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800841 descriptor.reset();
842 return;
843 }
844 });
845 return descriptor;
846 }
847
848 SimpleParamReflector(sp<Base> base)
849 : mBase(base) { }
850
851 sp<Base> mBase;
852 };
853
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700854 return std::make_shared<SimpleParamReflector>(mBase1_0);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800855};
856
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700857std::vector<std::string> const& Codec2Client::GetServiceNames() {
858 static std::vector<std::string> sServiceNames{[]() {
859 using ::android::hardware::media::c2::V1_0::IComponentStore;
860 using ::android::hidl::manager::V1_2::IServiceManager;
861
862 while (true) {
863 sp<IServiceManager> serviceManager = IServiceManager::getService();
864 CHECK(serviceManager) << "Hardware service manager is not running.";
865
866 // There are three categories of services based on names.
867 std::vector<std::string> defaultNames; // Prefixed with "default"
868 std::vector<std::string> vendorNames; // Prefixed with "vendor"
869 std::vector<std::string> otherNames; // Others
870 Return<void> transResult;
871 transResult = serviceManager->listManifestByInterface(
872 IComponentStore::descriptor,
873 [&defaultNames, &vendorNames, &otherNames](
874 hidl_vec<hidl_string> const& instanceNames) {
875 for (hidl_string const& instanceName : instanceNames) {
876 char const* name = instanceName.c_str();
877 if (strncmp(name, "default", 7) == 0) {
878 defaultNames.emplace_back(name);
879 } else if (strncmp(name, "vendor", 6) == 0) {
880 vendorNames.emplace_back(name);
881 } else {
882 otherNames.emplace_back(name);
883 }
884 }
885 });
886 if (transResult.isOk()) {
887 // Sort service names in each category.
888 std::sort(defaultNames.begin(), defaultNames.end());
889 std::sort(vendorNames.begin(), vendorNames.end());
890 std::sort(otherNames.begin(), otherNames.end());
891
892 // Concatenate the three lists in this order: default, vendor,
893 // other.
894 std::vector<std::string>& names = defaultNames;
895 names.reserve(names.size() + vendorNames.size() + otherNames.size());
896 names.insert(names.end(),
897 std::make_move_iterator(vendorNames.begin()),
898 std::make_move_iterator(vendorNames.end()));
899 names.insert(names.end(),
900 std::make_move_iterator(otherNames.begin()),
901 std::make_move_iterator(otherNames.end()));
902
903 // Summarize to logcat.
904 if (names.empty()) {
905 LOG(INFO) << "No Codec2 services declared in the manifest.";
906 } else {
907 std::stringstream stringOutput;
908 stringOutput << "Available Codec2 services:";
909 for (std::string const& name : names) {
910 stringOutput << " \"" << name << "\"";
911 }
912 LOG(INFO) << stringOutput.str();
913 }
914
915 return names;
916 }
917 LOG(ERROR) << "Could not retrieve the list of service instances of "
918 << IComponentStore::descriptor
919 << ". Retrying...";
920 }
921 }()};
922 return sServiceNames;
923}
924
Pawin Vongmasa36653902018-11-15 00:10:25 -0800925std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa83d2c552020-03-05 04:36:08 -0800926 const char* name,
927 bool setAsPreferredCodec2ComponentStore) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700928 size_t index = getServiceIndex(name);
Pawin Vongmasa83d2c552020-03-05 04:36:08 -0800929 if (index == GetServiceNames().size()) {
930 if (setAsPreferredCodec2ComponentStore) {
931 LOG(WARNING) << "CreateFromService(" << name
932 << ") -- preferred C2ComponentStore not set.";
933 }
934 return nullptr;
935 }
936 std::shared_ptr<Codec2Client> client = _CreateFromIndex(index);
937 if (setAsPreferredCodec2ComponentStore) {
938 SetPreferredCodec2ComponentStore(
939 std::make_shared<Client2Store>(client));
940 LOG(INFO) << "CreateFromService(" << name
941 << ") -- service set as preferred C2ComponentStore.";
942 }
943 return client;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800944}
945
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700946std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
947 CreateFromAllServices() {
948 std::vector<std::shared_ptr<Codec2Client>> clients(
949 GetServiceNames().size());
950 for (size_t i = GetServiceNames().size(); i > 0; ) {
951 --i;
952 clients[i] = _CreateFromIndex(i);
953 }
954 return clients;
955}
956
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700957std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700958 std::string const& name = GetServiceNames()[index];
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800959 LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700960 sp<Base> baseStore = Base::getService(name);
961 CHECK(baseStore) << "Codec2 service \"" << name << "\""
962 " inaccessible for unknown reasons.";
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800963 LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700964 return std::make_shared<Codec2Client>(baseStore, index);
965}
966
967c2_status_t Codec2Client::ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800968 const std::string &key,
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700969 size_t numberOfAttempts,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800970 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
971 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800972 c2_status_t status = C2_NO_INIT; // no IComponentStores present
973
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700974 // Cache the mapping key -> index of Codec2Client in Cache::List().
Pawin Vongmasa36653902018-11-15 00:10:25 -0800975 static std::mutex key2IndexMutex;
976 static std::map<std::string, size_t> key2Index;
977
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800978 // By default try all stores. However, try the last known client first. If
979 // the last known client fails, retry once. We do this by pushing the last
980 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800981 std::deque<size_t> indices;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700982 for (size_t index = Cache::List().size(); index > 0; ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800983 indices.push_front(--index);
984 }
985
986 bool wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700987 {
988 std::scoped_lock lock{key2IndexMutex};
989 auto it = key2Index.find(key);
990 if (it != key2Index.end()) {
991 indices.push_front(it->second);
992 wasMapped = true;
993 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800994 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800995
996 for (size_t index : indices) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700997 Cache& cache = Cache::List()[index];
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700998 for (size_t tries = numberOfAttempts; tries > 0; --tries) {
999 std::shared_ptr<Codec2Client> client{cache.getClient()};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001000 status = predicate(client);
1001 if (status == C2_OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001002 std::scoped_lock lock{key2IndexMutex};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001003 key2Index[key] = index; // update last known client index
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001004 return C2_OK;
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001005 } else if (status == C2_TRANSACTION_FAILED) {
1006 LOG(WARNING) << "\"" << key << "\" failed for service \""
1007 << client->getName()
1008 << "\" due to transaction failure. "
1009 << "(Service may have crashed.)"
1010 << (tries > 1 ? " Retrying..." : "");
1011 cache.invalidate();
1012 continue;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001013 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001014 if (wasMapped) {
1015 LOG(INFO) << "\"" << key << "\" became invalid in service \""
1016 << client->getName() << "\". Retrying...";
1017 wasMapped = false;
1018 }
1019 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001020 }
1021 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001022 return status; // return the last status from a valid client
Pawin Vongmasa36653902018-11-15 00:10:25 -08001023}
1024
1025std::shared_ptr<Codec2Client::Component>
1026 Codec2Client::CreateComponentByName(
1027 const char* componentName,
1028 const std::shared_ptr<Listener>& listener,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001029 std::shared_ptr<Codec2Client>* owner,
1030 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001031 std::string key{"create:"};
1032 key.append(componentName);
1033 std::shared_ptr<Component> component;
1034 c2_status_t status = ForAllServices(
1035 key,
1036 numberOfAttempts,
1037 [owner, &component, componentName, &listener](
1038 const std::shared_ptr<Codec2Client> &client)
1039 -> c2_status_t {
1040 c2_status_t status = client->createComponent(componentName,
1041 listener,
1042 &component);
1043 if (status == C2_OK) {
1044 if (owner) {
1045 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001046 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001047 } else if (status != C2_NOT_FOUND) {
1048 LOG(DEBUG) << "IComponentStore("
1049 << client->getServiceName()
1050 << ")::createComponent(\"" << componentName
1051 << "\") returned status = "
1052 << status << ".";
1053 }
1054 return status;
1055 });
1056 if (status != C2_OK) {
1057 LOG(DEBUG) << "Failed to create component \"" << componentName
1058 << "\" from all known services. "
1059 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001060 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001061 return component;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001062}
1063
1064std::shared_ptr<Codec2Client::Interface>
1065 Codec2Client::CreateInterfaceByName(
1066 const char* interfaceName,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001067 std::shared_ptr<Codec2Client>* owner,
1068 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001069 std::string key{"create:"};
1070 key.append(interfaceName);
1071 std::shared_ptr<Interface> interface;
1072 c2_status_t status = ForAllServices(
1073 key,
1074 numberOfAttempts,
1075 [owner, &interface, interfaceName](
1076 const std::shared_ptr<Codec2Client> &client)
1077 -> c2_status_t {
1078 c2_status_t status = client->createInterface(interfaceName,
1079 &interface);
1080 if (status == C2_OK) {
1081 if (owner) {
1082 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001083 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001084 } else if (status != C2_NOT_FOUND) {
1085 LOG(DEBUG) << "IComponentStore("
1086 << client->getServiceName()
1087 << ")::createInterface(\"" << interfaceName
1088 << "\") returned status = "
1089 << status << ".";
1090 }
1091 return status;
1092 });
1093 if (status != C2_OK) {
1094 LOG(DEBUG) << "Failed to create interface \"" << interfaceName
1095 << "\" from all known services. "
1096 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001097 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001098 return interface;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001099}
1100
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001101std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
1102 static std::vector<C2Component::Traits> sList{[]() {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001103 std::vector<C2Component::Traits> list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001104 for (Cache& cache : Cache::List()) {
1105 std::vector<C2Component::Traits> const& traits = cache.getTraits();
1106 list.insert(list.end(), traits.begin(), traits.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001107 }
1108 return list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001109 }()};
1110 return sList;
1111}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001112
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001113std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
1114 char const* serviceName) {
Pawin Vongmasa18588322019-05-18 01:52:13 -07001115 int32_t inputSurfaceSetting = ::android::base::GetIntProperty(
1116 "debug.stagefright.c2inputsurface", int32_t(0));
1117 if (inputSurfaceSetting <= 0) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001118 return nullptr;
1119 }
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001120 size_t index = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001121 if (serviceName) {
1122 index = getServiceIndex(serviceName);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001123 if (index == GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001124 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
1125 << serviceName << "\"";
1126 }
1127 }
1128
1129 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001130 if (index != GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001131 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
1132 if (client->createInputSurface(&inputSurface) == C2_OK) {
1133 return inputSurface;
1134 }
1135 }
1136 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
1137 "from all services...";
1138 for (Cache& cache : Cache::List()) {
1139 std::shared_ptr<Codec2Client> client = cache.getClient();
1140 if (client->createInputSurface(&inputSurface) == C2_OK) {
1141 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
1142 "service \"" << client->getServiceName() << "\"";
1143 return inputSurface;
1144 }
1145 }
1146 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
1147 "from all services";
1148 return nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001149}
1150
1151// Codec2Client::Listener
1152
1153Codec2Client::Listener::~Listener() {
1154}
1155
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001156// Codec2Client::Interface
1157Codec2Client::Interface::Interface(const sp<Base>& base)
1158 : Configurable{
1159 [base]() -> sp<IConfigurable> {
1160 Return<sp<IConfigurable>> transResult =
1161 base->getConfigurable();
1162 return transResult.isOk() ?
1163 static_cast<sp<IConfigurable>>(transResult) :
1164 nullptr;
1165 }()
1166 },
1167 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001168}
1169
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001170// Codec2Client::Component
1171Codec2Client::Component::Component(const sp<Base>& base)
1172 : Configurable{
1173 [base]() -> sp<IConfigurable> {
1174 Return<sp<IComponentInterface>> transResult1 =
1175 base->getInterface();
1176 if (!transResult1.isOk()) {
1177 return nullptr;
1178 }
1179 Return<sp<IConfigurable>> transResult2 =
1180 static_cast<sp<IComponentInterface>>(transResult1)->
1181 getConfigurable();
1182 return transResult2.isOk() ?
1183 static_cast<sp<IConfigurable>>(transResult2) :
1184 nullptr;
1185 }()
1186 },
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001187 mBase1_0{base},
1188 mBase1_1{Base1_1::castFrom(base)},
1189 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1190 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1191}
1192
1193Codec2Client::Component::Component(const sp<Base1_1>& base)
1194 : Configurable{
1195 [base]() -> sp<IConfigurable> {
1196 Return<sp<IComponentInterface>> transResult1 =
1197 base->getInterface();
1198 if (!transResult1.isOk()) {
1199 return nullptr;
1200 }
1201 Return<sp<IConfigurable>> transResult2 =
1202 static_cast<sp<IComponentInterface>>(transResult1)->
1203 getConfigurable();
1204 return transResult2.isOk() ?
1205 static_cast<sp<IConfigurable>>(transResult2) :
1206 nullptr;
1207 }()
1208 },
1209 mBase1_0{base},
1210 mBase1_1{base},
1211 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1212 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001213}
1214
1215Codec2Client::Component::~Component() {
1216}
1217
1218c2_status_t Codec2Client::Component::createBlockPool(
1219 C2Allocator::id_t id,
1220 C2BlockPool::local_id_t* blockPoolId,
1221 std::shared_ptr<Codec2Client::Configurable>* configurable) {
1222 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001223 Return<void> transStatus = mBase1_0->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001224 static_cast<uint32_t>(id),
1225 [&status, blockPoolId, configurable](
1226 Status s,
1227 uint64_t pId,
1228 const sp<IConfigurable>& c) {
1229 status = static_cast<c2_status_t>(s);
1230 configurable->reset();
1231 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001232 LOG(DEBUG) << "createBlockPool -- call failed: "
1233 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001234 return;
1235 }
1236 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001237 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001238 });
1239 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001240 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001241 return C2_TRANSACTION_FAILED;
1242 }
1243 return status;
1244}
1245
1246c2_status_t Codec2Client::Component::destroyBlockPool(
1247 C2BlockPool::local_id_t localId) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001248 Return<Status> transResult = mBase1_0->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001249 static_cast<uint64_t>(localId));
1250 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001251 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001252 return C2_TRANSACTION_FAILED;
1253 }
1254 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1255}
1256
Wonsik Kimab34ed62019-01-31 15:28:46 -08001257void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001258 const std::list<std::unique_ptr<C2Work>> &workItems) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001259 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001260 mOutputBufferQueue->holdBufferQueueBlocks(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001261}
1262
1263c2_status_t Codec2Client::Component::queue(
1264 std::list<std::unique_ptr<C2Work>>* const items) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001265 WorkBundle workBundle;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001266 if (!objcpy(&workBundle, *items, mBufferPoolSender.get())) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001267 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001268 return C2_TRANSACTION_FAILED;
1269 }
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001270 Return<Status> transStatus = mBase1_0->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001271 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001272 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001273 return C2_TRANSACTION_FAILED;
1274 }
1275 c2_status_t status =
1276 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1277 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001278 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001279 }
1280 return status;
1281}
1282
1283c2_status_t Codec2Client::Component::flush(
1284 C2Component::flush_mode_t mode,
1285 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
1286 (void)mode; // Flush mode isn't supported in HIDL yet.
1287 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001288 Return<void> transStatus = mBase1_0->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001289 [&status, flushedWork](
1290 Status s, const WorkBundle& wb) {
1291 status = static_cast<c2_status_t>(s);
1292 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001293 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001294 return;
1295 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001296 if (!objcpy(flushedWork, wb)) {
1297 status = C2_CORRUPTED;
1298 } else {
1299 status = C2_OK;
1300 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001301 });
1302 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001303 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001304 return C2_TRANSACTION_FAILED;
1305 }
1306
1307 // Indices of flushed work items.
1308 std::vector<uint64_t> flushedIndices;
1309 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
1310 if (work) {
1311 if (work->worklets.empty()
1312 || !work->worklets.back()
1313 || (work->worklets.back()->output.flags &
1314 C2FrameData::FLAG_INCOMPLETE) == 0) {
1315 // input is complete
1316 flushedIndices.emplace_back(
1317 work->input.ordinal.frameIndex.peeku());
1318 }
1319 }
1320 }
1321
Pawin Vongmasa36653902018-11-15 00:10:25 -08001322 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001323 mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001324
1325 return status;
1326}
1327
1328c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001329 Return<Status> transStatus = mBase1_0->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001330 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1331 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001332 LOG(ERROR) << "drain -- 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) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001339 }
1340 return status;
1341}
1342
1343c2_status_t Codec2Client::Component::start() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001344 Return<Status> transStatus = mBase1_0->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001345 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001346 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001347 return C2_TRANSACTION_FAILED;
1348 }
1349 c2_status_t status =
1350 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1351 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001352 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001353 }
1354 return status;
1355}
1356
1357c2_status_t Codec2Client::Component::stop() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001358 Return<Status> transStatus = mBase1_0->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001359 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001360 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001361 return C2_TRANSACTION_FAILED;
1362 }
1363 c2_status_t status =
1364 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1365 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001366 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001367 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001368 return status;
1369}
1370
1371c2_status_t Codec2Client::Component::reset() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001372 Return<Status> transStatus = mBase1_0->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001373 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001374 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001375 return C2_TRANSACTION_FAILED;
1376 }
1377 c2_status_t status =
1378 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1379 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001380 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001381 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001382 return status;
1383}
1384
1385c2_status_t Codec2Client::Component::release() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001386 Return<Status> transStatus = mBase1_0->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001387 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001388 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001389 return C2_TRANSACTION_FAILED;
1390 }
1391 c2_status_t status =
1392 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1393 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001394 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001395 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001396 return status;
1397}
1398
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001399c2_status_t Codec2Client::Component::configureVideoTunnel(
1400 uint32_t avSyncHwId,
1401 native_handle_t** sidebandHandle) {
1402 *sidebandHandle = nullptr;
1403 if (!mBase1_1) {
1404 return C2_OMITTED;
1405 }
1406 c2_status_t status{};
1407 Return<void> transStatus = mBase1_1->configureVideoTunnel(avSyncHwId,
1408 [&status, sidebandHandle](
1409 Status s, hardware::hidl_handle const& h) {
1410 status = static_cast<c2_status_t>(s);
1411 if (h.getNativeHandle()) {
1412 *sidebandHandle = native_handle_clone(h.getNativeHandle());
1413 }
1414 });
1415 if (!transStatus.isOk()) {
1416 LOG(ERROR) << "configureVideoTunnel -- transaction failed.";
1417 return C2_TRANSACTION_FAILED;
1418 }
1419 return status;
1420}
1421
Pawin Vongmasa36653902018-11-15 00:10:25 -08001422c2_status_t Codec2Client::Component::setOutputSurface(
1423 C2BlockPool::local_id_t blockPoolId,
1424 const sp<IGraphicBufferProducer>& surface,
1425 uint32_t generation) {
Sungtak Lee08515812019-06-05 11:16:32 -07001426 uint64_t bqId = 0;
1427 sp<IGraphicBufferProducer> nullIgbp;
1428 sp<HGraphicBufferProducer2> nullHgbp;
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08001429
Sungtak Lee08515812019-06-05 11:16:32 -07001430 sp<HGraphicBufferProducer2> igbp = surface ?
1431 surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
1432 if (surface && !igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001433 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001434 }
1435
Sungtak Lee08515812019-06-05 11:16:32 -07001436 if (!surface) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001437 mOutputBufferQueue->configure(nullIgbp, generation, 0);
Sungtak Lee08515812019-06-05 11:16:32 -07001438 } else if (surface->getUniqueId(&bqId) != OK) {
1439 LOG(ERROR) << "setOutputSurface -- "
1440 "cannot obtain bufferqueue id.";
1441 bqId = 0;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001442 mOutputBufferQueue->configure(nullIgbp, generation, 0);
Sungtak Lee08515812019-06-05 11:16:32 -07001443 } else {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001444 mOutputBufferQueue->configure(surface, generation, bqId);
Sungtak Lee08515812019-06-05 11:16:32 -07001445 }
1446 ALOGD("generation remote change %u", generation);
1447
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001448 Return<Status> transStatus = mBase1_0->setOutputSurface(
Sungtak Lee08515812019-06-05 11:16:32 -07001449 static_cast<uint64_t>(blockPoolId),
1450 bqId == 0 ? nullHgbp : igbp);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001451 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001452 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001453 return C2_TRANSACTION_FAILED;
1454 }
1455 c2_status_t status =
1456 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1457 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001458 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001459 }
1460 return status;
1461}
1462
1463status_t Codec2Client::Component::queueToOutputSurface(
1464 const C2ConstGraphicBlock& block,
1465 const QueueBufferInput& input,
1466 QueueBufferOutput* output) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001467 return mOutputBufferQueue->outputBuffer(block, input, output);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001468}
1469
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001470c2_status_t Codec2Client::Component::connectToInputSurface(
1471 const std::shared_ptr<InputSurface>& inputSurface,
1472 std::shared_ptr<InputSurfaceConnection>* connection) {
1473 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001474 Return<void> transStatus = mBase1_0->connectToInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001475 inputSurface->mBase,
1476 [&status, connection](
1477 Status s, const sp<IInputSurfaceConnection>& c) {
1478 status = static_cast<c2_status_t>(s);
1479 if (status != C2_OK) {
1480 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1481 << status << ".";
1482 return;
1483 }
1484 *connection = std::make_shared<InputSurfaceConnection>(c);
1485 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001486 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001487 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001488 return C2_TRANSACTION_FAILED;
1489 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001490 return status;
1491}
1492
1493c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001494 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001495 const sp<HGraphicBufferSource>& source,
1496 std::shared_ptr<InputSurfaceConnection>* connection) {
1497 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001498 Return<void> transStatus = mBase1_0->connectToOmxInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001499 producer, source,
1500 [&status, connection](
1501 Status s, const sp<IInputSurfaceConnection>& c) {
1502 status = static_cast<c2_status_t>(s);
1503 if (status != C2_OK) {
1504 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1505 << status << ".";
1506 return;
1507 }
1508 *connection = std::make_shared<InputSurfaceConnection>(c);
1509 });
1510 if (!transStatus.isOk()) {
1511 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1512 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001513 }
1514 return status;
1515}
1516
1517c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001518 Return<Status> transStatus = mBase1_0->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001519 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001520 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001521 return C2_TRANSACTION_FAILED;
1522 }
1523 c2_status_t status =
1524 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1525 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001526 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1527 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001528 }
1529 return status;
1530}
1531
1532c2_status_t Codec2Client::Component::setDeathListener(
1533 const std::shared_ptr<Component>& component,
1534 const std::shared_ptr<Listener>& listener) {
1535
1536 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1537 std::weak_ptr<Component> component;
1538 std::weak_ptr<Listener> base;
1539
1540 virtual void serviceDied(
1541 uint64_t /* cookie */,
1542 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1543 ) override {
1544 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1545 listener->onDeath(component);
1546 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001547 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001548 }
1549 }
1550 };
1551
1552 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1553 deathRecipient->base = listener;
1554 deathRecipient->component = component;
1555
1556 component->mDeathRecipient = deathRecipient;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001557 Return<bool> transResult = component->mBase1_0->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001558 component->mDeathRecipient, 0);
1559 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001560 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001561 return C2_TRANSACTION_FAILED;
1562 }
1563 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001564 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001565 return C2_CORRUPTED;
1566 }
1567 return C2_OK;
1568}
1569
1570// Codec2Client::InputSurface
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001571Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base)
1572 : Configurable{
1573 [base]() -> sp<IConfigurable> {
1574 Return<sp<IConfigurable>> transResult =
1575 base->getConfigurable();
1576 return transResult.isOk() ?
1577 static_cast<sp<IConfigurable>>(transResult) :
1578 nullptr;
1579 }()
1580 },
1581 mBase{base},
1582 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001583 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
1584 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001585 base->getGraphicBufferProducer();
1586 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001587 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001588 nullptr;
1589 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001590}
1591
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001592sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08001593 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1594 return mGraphicBufferProducer;
1595}
1596
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001597sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001598 return mBase;
1599}
1600
1601// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08001602Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001603 const sp<IInputSurfaceConnection>& base)
1604 : Configurable{
1605 [base]() -> sp<IConfigurable> {
1606 Return<sp<IConfigurable>> transResult =
1607 base->getConfigurable();
1608 return transResult.isOk() ?
1609 static_cast<sp<IConfigurable>>(transResult) :
1610 nullptr;
1611 }()
1612 },
1613 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001614}
1615
1616c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001617 Return<Status> transResult = mBase->disconnect();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001618 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1619}
1620
1621} // namespace android
1622