blob: 09452c49bb260a7b80280c161af9fb949c204e69 [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>
Lajos Molnar78aa7c92021-02-18 21:39:01 -080024#include <C2Config.h> // for C2StreamUsageTuning
Pawin Vongmasabf69de92019-10-29 06:21:27 -070025#include <C2PlatformSupport.h>
26
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -080027#include <android/binder_auto_utils.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070028#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
29#include <android/hardware/media/c2/1.0/IComponent.h>
30#include <android/hardware/media/c2/1.0/IComponentInterface.h>
31#include <android/hardware/media/c2/1.0/IComponentListener.h>
32#include <android/hardware/media/c2/1.0/IComponentStore.h>
33#include <android/hardware/media/c2/1.0/IConfigurable.h>
34#include <android/hidl/manager/1.2/IServiceManager.h>
35
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -080036#include <aidl/android/hardware/media/c2/FieldSupportedValues.h>
37#include <aidl/android/hardware/media/c2/FieldSupportedValuesQuery.h>
38#include <aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.h>
39#include <aidl/android/hardware/media/c2/IComponent.h>
40#include <aidl/android/hardware/media/c2/IComponentInterface.h>
41#include <aidl/android/hardware/media/c2/IComponentStore.h>
42#include <aidl/android/hardware/media/c2/IConfigurable.h>
43#include <aidl/android/hardware/media/c2/ParamDescriptor.h>
44
Pawin Vongmasabf69de92019-10-29 06:21:27 -070045#include <android-base/properties.h>
46#include <bufferpool/ClientManager.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070047#include <codec2/hidl/1.0/types.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070048#include <codec2/hidl/1.1/types.h>
Sungtak Lee8577dab2021-03-12 02:25:50 -080049#include <codec2/hidl/1.2/types.h>
Sungtak Leea714f112021-03-16 05:40:03 -070050#include <codec2/hidl/output.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070051
52#include <cutils/native_handle.h>
53#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
54#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
Lajos Molnar78aa7c92021-02-18 21:39:01 -080055#include <hardware/gralloc.h> // for GRALLOC_USAGE_*
Pawin Vongmasabf69de92019-10-29 06:21:27 -070056#include <hidl/HidlSupport.h>
Lajos Molnar78aa7c92021-02-18 21:39:01 -080057#include <system/window.h> // for NATIVE_WINDOW_QUERY_*
58#include <media/stagefright/foundation/ADebug.h> // for asString(status_t)
Pawin Vongmasa36653902018-11-15 00:10:25 -080059
60#include <deque>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070061#include <iterator>
Pawin Vongmasa36653902018-11-15 00:10:25 -080062#include <limits>
63#include <map>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070064#include <mutex>
65#include <sstream>
66#include <thread>
Pawin Vongmasa36653902018-11-15 00:10:25 -080067#include <type_traits>
68#include <vector>
69
Pawin Vongmasa36653902018-11-15 00:10:25 -080070namespace android {
71
72using ::android::hardware::hidl_vec;
73using ::android::hardware::hidl_string;
74using ::android::hardware::Return;
75using ::android::hardware::Void;
Pawin Vongmasa36653902018-11-15 00:10:25 -080076
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080077using HGraphicBufferProducer1 = ::android::hardware::graphics::bufferqueue::
78 V1_0::IGraphicBufferProducer;
79using HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
80 V2_0::IGraphicBufferProducer;
81using B2HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
82 V2_0::utils::B2HGraphicBufferProducer;
83using H2BGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
84 V2_0::utils::H2BGraphicBufferProducer;
Sungtak Leea714f112021-03-16 05:40:03 -070085using ::android::hardware::media::c2::V1_2::SurfaceSyncObj;
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080086
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -080087namespace bufferpool_hidl = ::android::hardware::media::bufferpool::V2_0;
88namespace c2_aidl = ::aidl::android::hardware::media::c2;
89namespace c2_hidl_base = ::android::hardware::media::c2;
90namespace c2_hidl = ::android::hardware::media::c2::V1_2;
91
92using c2_hidl::utils::operator<<;
93
Pawin Vongmasa36653902018-11-15 00:10:25 -080094namespace /* unnamed */ {
95
96// c2_status_t value that corresponds to hwbinder transaction failure.
97constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
98
Lajos Molnar78aa7c92021-02-18 21:39:01 -080099// By default prepare buffer to be displayed on any of the common surfaces
100constexpr uint64_t kDefaultConsumerUsage =
101 (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER);
102
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700103// Searches for a name in GetServiceNames() and returns the index found. If the
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700104// name is not found, the returned index will be equal to
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700105// GetServiceNames().size().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700106size_t getServiceIndex(char const* name) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700107 std::vector<std::string> const& names = Codec2Client::GetServiceNames();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700108 size_t i = 0;
109 for (; i < names.size(); ++i) {
110 if (name == names[i]) {
111 break;
112 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800113 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700114 return i;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800115}
116
Pawin Vongmasa83d2c552020-03-05 04:36:08 -0800117class Client2Store : public C2ComponentStore {
118 std::shared_ptr<Codec2Client> mClient;
119
120public:
121 Client2Store(std::shared_ptr<Codec2Client> const& client)
122 : mClient(client) { }
123
124 virtual ~Client2Store() = default;
125
126 virtual c2_status_t config_sm(
127 std::vector<C2Param*> const &params,
128 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
129 return mClient->config(params, C2_MAY_BLOCK, failures);
130 };
131
132 virtual c2_status_t copyBuffer(
133 std::shared_ptr<C2GraphicBuffer>,
134 std::shared_ptr<C2GraphicBuffer>) {
135 return C2_OMITTED;
136 }
137
138 virtual c2_status_t createComponent(
139 C2String, std::shared_ptr<C2Component>* const component) {
140 component->reset();
141 return C2_OMITTED;
142 }
143
144 virtual c2_status_t createInterface(
145 C2String, std::shared_ptr<C2ComponentInterface>* const interface) {
146 interface->reset();
147 return C2_OMITTED;
148 }
149
150 virtual c2_status_t query_sm(
151 std::vector<C2Param*> const& stackParams,
152 std::vector<C2Param::Index> const& heapParamIndices,
153 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
154 return mClient->query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
155 }
156
157 virtual c2_status_t querySupportedParams_nb(
158 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
159 return mClient->querySupportedParams(params);
160 }
161
162 virtual c2_status_t querySupportedValues_sm(
163 std::vector<C2FieldSupportedValuesQuery>& fields) const {
164 return mClient->querySupportedValues(fields, C2_MAY_BLOCK);
165 }
166
167 virtual C2String getName() const {
168 return mClient->getName();
169 }
170
171 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const {
172 return mClient->getParamReflector();
173 }
174
175 virtual std::vector<std::shared_ptr<C2Component::Traits const>> listComponents() {
176 return std::vector<std::shared_ptr<C2Component::Traits const>>();
177 }
178};
179
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700180} // unnamed namespace
181
182// This class caches a Codec2Client object and its component traits. The client
183// will be created the first time it is needed, and it can be refreshed if the
184// service dies (by calling invalidate()). The first time listComponents() is
185// called from the client, the result will be cached.
186class Codec2Client::Cache {
187 // Cached client
188 std::shared_ptr<Codec2Client> mClient;
189 mutable std::mutex mClientMutex;
190
191 // Cached component traits
192 std::vector<C2Component::Traits> mTraits;
193 std::once_flag mTraitsInitializationFlag;
194
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700195 // The index of the service. This is based on GetServiceNames().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700196 size_t mIndex;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700197 // Called by s() exactly once to initialize the cache. The index must be a
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700198 // valid index into the vector returned by GetServiceNames(). Calling
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700199 // init(index) will associate the cache to the service with name
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700200 // GetServiceNames()[index].
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700201 void init(size_t index) {
202 mIndex = index;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700203 }
204
205public:
206 Cache() = default;
207
208 // Initializes mClient if needed, then returns mClient.
209 // If the service is unavailable but listed in the manifest, this function
210 // will block indefinitely.
211 std::shared_ptr<Codec2Client> getClient() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700212 std::scoped_lock lock{mClientMutex};
213 if (!mClient) {
214 mClient = Codec2Client::_CreateFromIndex(mIndex);
215 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700216 CHECK(mClient) << "Failed to create Codec2Client to service \""
217 << GetServiceNames()[mIndex] << "\". (Index = "
218 << mIndex << ").";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700219 return mClient;
220 }
221
222 // Causes a subsequent call to getClient() to create a new client. This
223 // function should be called after the service dies.
224 //
225 // Note: This function is called only by ForAllServices().
226 void invalidate() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700227 std::scoped_lock lock{mClientMutex};
228 mClient = nullptr;
229 }
230
231 // Returns a list of traits for components supported by the service. This
232 // list is cached.
233 std::vector<C2Component::Traits> const& getTraits() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700234 std::call_once(mTraitsInitializationFlag, [this]() {
235 bool success{false};
236 // Spin until _listComponents() is successful.
237 while (true) {
238 std::shared_ptr<Codec2Client> client = getClient();
239 mTraits = client->_listComponents(&success);
240 if (success) {
241 break;
242 }
Pawin Vongmasa21617db2020-04-24 06:16:42 -0700243 invalidate();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700244 using namespace std::chrono_literals;
245 static constexpr auto kServiceRetryPeriod = 5s;
246 LOG(INFO) << "Failed to retrieve component traits from service "
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700247 "\"" << GetServiceNames()[mIndex] << "\". "
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700248 "Retrying...";
249 std::this_thread::sleep_for(kServiceRetryPeriod);
250 }
251 });
252 return mTraits;
253 }
254
255 // List() returns the list of all caches.
256 static std::vector<Cache>& List() {
257 static std::vector<Cache> sCaches{[]() {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700258 size_t numServices = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700259 std::vector<Cache> caches(numServices);
260 for (size_t i = 0; i < numServices; ++i) {
261 caches[i].init(i);
262 }
263 return caches;
264 }()};
265 return sCaches;
266 }
267};
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800268// Codec2ConfigurableClient::HidlImpl
Pawin Vongmasa36653902018-11-15 00:10:25 -0800269
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800270struct Codec2ConfigurableClient::HidlImpl : public Codec2ConfigurableClient::ImplBase {
271 typedef c2_hidl::IConfigurable Base;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800272
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800273 // base cannot be null.
274 explicit HidlImpl(const sp<Base>& base);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800275
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800276 const C2String& getName() const override {
277 return mName;
278 }
279
280 c2_status_t query(
281 const std::vector<C2Param*>& stackParams,
282 const std::vector<C2Param::Index> &heapParamIndices,
283 c2_blocking_t mayBlock,
284 std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
285
286 c2_status_t config(
287 const std::vector<C2Param*> &params,
288 c2_blocking_t mayBlock,
289 std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
290
291 c2_status_t querySupportedParams(
292 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
293 ) const override;
294
295 c2_status_t querySupportedValues(
296 std::vector<C2FieldSupportedValuesQuery>& fields,
297 c2_blocking_t mayBlock) const override;
298
299private:
300 sp<Base> mBase;
301 const C2String mName;
302};
303
304Codec2ConfigurableClient::HidlImpl::HidlImpl(const sp<Base>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800305 : mBase{base},
306 mName{[base]() -> C2String {
307 C2String outName;
308 Return<void> transStatus = base->getName(
309 [&outName](const hidl_string& name) {
310 outName = name.c_str();
311 });
312 return transStatus.isOk() ? outName : "";
313 }()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800314}
315
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800316c2_status_t Codec2ConfigurableClient::HidlImpl::query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800317 const std::vector<C2Param*> &stackParams,
318 const std::vector<C2Param::Index> &heapParamIndices,
319 c2_blocking_t mayBlock,
320 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800321 hidl_vec<c2_hidl::ParamIndex> indices(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800322 stackParams.size() + heapParamIndices.size());
323 size_t numIndices = 0;
324 for (C2Param* const& stackParam : stackParams) {
325 if (!stackParam) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800326 LOG(WARNING) << "query -- null stack param encountered.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800327 continue;
328 }
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800329 indices[numIndices++] = static_cast<c2_hidl::ParamIndex>(stackParam->index());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800330 }
331 size_t numStackIndices = numIndices;
332 for (const C2Param::Index& index : heapParamIndices) {
333 indices[numIndices++] =
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800334 static_cast<c2_hidl::ParamIndex>(static_cast<uint32_t>(index));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800335 }
336 indices.resize(numIndices);
337 if (heapParams) {
338 heapParams->reserve(heapParams->size() + numIndices);
339 }
340 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800341 Return<void> transStatus = mBase->query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800342 indices,
343 mayBlock == C2_MAY_BLOCK,
344 [&status, &numStackIndices, &stackParams, heapParams](
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800345 c2_hidl::Status s, const c2_hidl::Params& p) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800346 status = static_cast<c2_status_t>(s);
347 if (status != C2_OK && status != C2_BAD_INDEX) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800348 LOG(DEBUG) << "query -- call failed: "
349 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800350 return;
351 }
352 std::vector<C2Param*> paramPointers;
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800353 if (!c2_hidl::utils::parseParamsBlob(&paramPointers, p)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800354 LOG(ERROR) << "query -- error while parsing params.";
355 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800356 return;
357 }
358 size_t i = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800359 for (auto it = paramPointers.begin();
360 it != paramPointers.end(); ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800361 C2Param* paramPointer = *it;
362 if (numStackIndices > 0) {
363 --numStackIndices;
364 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800365 LOG(WARNING) << "query -- null stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800366 ++it;
367 continue;
368 }
369 for (; i < stackParams.size() && !stackParams[i]; ) {
370 ++i;
371 }
372 if (i >= stackParams.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800373 LOG(ERROR) << "query -- unexpected error.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800374 status = C2_CORRUPTED;
375 return;
376 }
377 if (stackParams[i]->index() != paramPointer->index()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800378 LOG(WARNING) << "query -- param skipped: "
379 "index = "
380 << stackParams[i]->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800381 stackParams[i++]->invalidate();
382 continue;
383 }
384 if (!stackParams[i++]->updateFrom(*paramPointer)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800385 LOG(WARNING) << "query -- param update failed: "
386 "index = "
387 << paramPointer->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800388 }
389 } else {
390 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800391 LOG(WARNING) << "query -- null heap param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800392 ++it;
393 continue;
394 }
395 if (!heapParams) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800396 LOG(WARNING) << "query -- "
397 "unexpected extra stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800398 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800399 heapParams->emplace_back(
400 C2Param::Copy(*paramPointer));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800401 }
402 }
403 ++it;
404 }
405 });
406 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800407 LOG(ERROR) << "query -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800408 return C2_TRANSACTION_FAILED;
409 }
410 return status;
411}
412
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800413c2_status_t Codec2ConfigurableClient::HidlImpl::config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800414 const std::vector<C2Param*> &params,
415 c2_blocking_t mayBlock,
416 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800417 c2_hidl::Params hidlParams;
418 if (!c2_hidl::utils::createParamsBlob(&hidlParams, params)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800419 LOG(ERROR) << "config -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800420 return C2_TRANSACTION_FAILED;
421 }
422 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800423 Return<void> transStatus = mBase->config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800424 hidlParams,
425 mayBlock == C2_MAY_BLOCK,
426 [&status, &params, failures](
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800427 c2_hidl::Status s,
428 const hidl_vec<c2_hidl::SettingResult> f,
429 const c2_hidl::Params& o) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800430 status = static_cast<c2_status_t>(s);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800431 if (status != C2_OK && status != C2_BAD_INDEX) {
432 LOG(DEBUG) << "config -- call failed: "
433 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800434 }
435 size_t i = failures->size();
436 failures->resize(i + f.size());
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800437 for (const c2_hidl::SettingResult& sf : f) {
438 if (!c2_hidl::utils::objcpy(&(*failures)[i++], sf)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800439 LOG(ERROR) << "config -- "
440 << "invalid SettingResult returned.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800441 return;
442 }
443 }
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800444 if (!c2_hidl::utils::updateParamsFromBlob(params, o)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800445 LOG(ERROR) << "config -- "
446 << "failed to parse returned params.";
447 status = C2_CORRUPTED;
448 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800449 });
450 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800451 LOG(ERROR) << "config -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800452 return C2_TRANSACTION_FAILED;
453 }
454 return status;
455}
456
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800457c2_status_t Codec2ConfigurableClient::HidlImpl::querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800458 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
459 // TODO: Cache and query properly!
460 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800461 Return<void> transStatus = mBase->querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800462 std::numeric_limits<uint32_t>::min(),
463 std::numeric_limits<uint32_t>::max(),
464 [&status, params](
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800465 c2_hidl::Status s,
466 const hidl_vec<c2_hidl::ParamDescriptor>& p) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800467 status = static_cast<c2_status_t>(s);
468 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800469 LOG(DEBUG) << "querySupportedParams -- call failed: "
470 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800471 return;
472 }
473 size_t i = params->size();
474 params->resize(i + p.size());
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800475 for (const c2_hidl::ParamDescriptor& sp : p) {
476 if (!c2_hidl::utils::objcpy(&(*params)[i++], sp)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800477 LOG(ERROR) << "querySupportedParams -- "
478 << "invalid returned ParamDescriptor.";
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) << "querySupportedParams -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800485 return C2_TRANSACTION_FAILED;
486 }
487 return status;
488}
489
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800490c2_status_t Codec2ConfigurableClient::HidlImpl::querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800491 std::vector<C2FieldSupportedValuesQuery>& fields,
492 c2_blocking_t mayBlock) const {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800493 hidl_vec<c2_hidl::FieldSupportedValuesQuery> inFields(fields.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800494 for (size_t i = 0; i < fields.size(); ++i) {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800495 if (!c2_hidl::utils::objcpy(&inFields[i], fields[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800496 LOG(ERROR) << "querySupportedValues -- bad input";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800497 return C2_TRANSACTION_FAILED;
498 }
499 }
500
501 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800502 Return<void> transStatus = mBase->querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800503 inFields,
504 mayBlock == C2_MAY_BLOCK,
505 [&status, &inFields, &fields](
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800506 c2_hidl::Status s,
507 const hidl_vec<c2_hidl::FieldSupportedValuesQueryResult>& r) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800508 status = static_cast<c2_status_t>(s);
509 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800510 LOG(DEBUG) << "querySupportedValues -- call failed: "
511 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800512 return;
513 }
514 if (r.size() != fields.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800515 LOG(ERROR) << "querySupportedValues -- "
516 "input and output lists "
517 "have different sizes.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800518 status = C2_CORRUPTED;
519 return;
520 }
521 for (size_t i = 0; i < fields.size(); ++i) {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800522 if (!c2_hidl::utils::objcpy(&fields[i], inFields[i], r[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800523 LOG(ERROR) << "querySupportedValues -- "
524 "invalid returned value.";
525 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800526 return;
527 }
528 }
529 });
530 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800531 LOG(ERROR) << "querySupportedValues -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800532 return C2_TRANSACTION_FAILED;
533 }
534 return status;
535}
536
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800537// Codec2ConfigurableClient::AidlImpl
538
539struct Codec2ConfigurableClient::AidlImpl : public Codec2ConfigurableClient::ImplBase {
540 typedef c2_aidl::IConfigurable Base;
541
542 // base cannot be null.
543 explicit AidlImpl(const std::shared_ptr<Base>& base);
544
545 const C2String& getName() const override {
546 return mName;
547 }
548
549 c2_status_t query(
550 const std::vector<C2Param*>& stackParams,
551 const std::vector<C2Param::Index> &heapParamIndices,
552 c2_blocking_t mayBlock,
553 std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
554
555 c2_status_t config(
556 const std::vector<C2Param*> &params,
557 c2_blocking_t mayBlock,
558 std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
559
560 c2_status_t querySupportedParams(
561 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
562 ) const override;
563
564 c2_status_t querySupportedValues(
565 std::vector<C2FieldSupportedValuesQuery>& fields,
566 c2_blocking_t mayBlock) const override;
567
568private:
569 std::shared_ptr<Base> mBase;
570 const C2String mName;
571};
572
573Codec2ConfigurableClient::AidlImpl::AidlImpl(const std::shared_ptr<Base>& base)
574 : mBase{base},
575 mName{[base]() -> C2String {
576 std::string outName;
577 ndk::ScopedAStatus status = base->getName(&outName);
578 return status.isOk() ? outName : "";
579 }()} {
580}
581
582c2_status_t Codec2ConfigurableClient::AidlImpl::query(
583 const std::vector<C2Param*> &stackParams,
584 const std::vector<C2Param::Index> &heapParamIndices,
585 c2_blocking_t mayBlock,
586 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
587 (void)stackParams, (void)heapParamIndices, (void)mayBlock, (void)heapParams;
588 // TODO: implementation
589 return C2_OMITTED;
590}
591
592c2_status_t Codec2ConfigurableClient::AidlImpl::config(
593 const std::vector<C2Param*> &params,
594 c2_blocking_t mayBlock,
595 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
596 (void)params, (void)mayBlock, (void)failures;
597 // TODO: implementation
598 return C2_OMITTED;
599}
600
601c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedParams(
602 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
603 (void)params;
604 // TODO: implementation
605 return C2_OMITTED;
606}
607
608c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedValues(
609 std::vector<C2FieldSupportedValuesQuery>& fields,
610 c2_blocking_t mayBlock) const {
611 (void)fields, (void)mayBlock;
612 // TODO: implementation
613 return C2_OMITTED;
614}
615
616// Codec2ConfigurableClient
617
618Codec2ConfigurableClient::Codec2ConfigurableClient(const sp<HidlBase> &hidlBase)
619 : mImpl(new Codec2ConfigurableClient::HidlImpl(hidlBase)) {
620}
621
622Codec2ConfigurableClient::Codec2ConfigurableClient(
623 const std::shared_ptr<AidlBase> &aidlBase)
624 : mImpl(new Codec2ConfigurableClient::AidlImpl(aidlBase)) {
625}
626
627const C2String& Codec2ConfigurableClient::getName() const {
628 return mImpl->getName();
629}
630
631c2_status_t Codec2ConfigurableClient::query(
632 const std::vector<C2Param*>& stackParams,
633 const std::vector<C2Param::Index> &heapParamIndices,
634 c2_blocking_t mayBlock,
635 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
636 return mImpl->query(stackParams, heapParamIndices, mayBlock, heapParams);
637}
638
639c2_status_t Codec2ConfigurableClient::config(
640 const std::vector<C2Param*> &params,
641 c2_blocking_t mayBlock,
642 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
643 return mImpl->config(params, mayBlock, failures);
644}
645
646c2_status_t Codec2ConfigurableClient::querySupportedParams(
647 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
648 return mImpl->querySupportedParams(params);
649}
650
651c2_status_t Codec2ConfigurableClient::querySupportedValues(
652 std::vector<C2FieldSupportedValuesQuery>& fields,
653 c2_blocking_t mayBlock) const {
654 return mImpl->querySupportedValues(fields, mayBlock);
655}
656
657
Pawin Vongmasa36653902018-11-15 00:10:25 -0800658// Codec2Client::Component::HidlListener
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800659struct Codec2Client::Component::HidlListener : public c2_hidl::IComponentListener {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800660 std::weak_ptr<Component> component;
661 std::weak_ptr<Listener> base;
662
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800663 virtual Return<void> onWorkDone(const c2_hidl::WorkBundle& workBundle) override {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800664 std::list<std::unique_ptr<C2Work>> workItems;
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800665 if (!c2_hidl::utils::objcpy(&workItems, workBundle)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800666 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800667 return Void();
668 }
669 // release input buffers potentially held by the component from queue
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800670 std::shared_ptr<Codec2Client::Component> strongComponent =
671 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800672 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800673 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800674 }
675 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800676 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800677 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800678 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800679 }
680 return Void();
681 }
682
683 virtual Return<void> onTripped(
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800684 const hidl_vec<c2_hidl::SettingResult>& settingResults) override {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800685 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
686 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800687 for (size_t i = 0; i < settingResults.size(); ++i) {
688 std::unique_ptr<C2SettingResult> c2SettingResult;
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800689 if (!c2_hidl::utils::objcpy(&c2SettingResult, settingResults[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800690 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800691 return Void();
692 }
693 c2SettingResults[i] = std::move(c2SettingResult);
694 }
695 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
696 listener->onTripped(component, c2SettingResults);
697 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800698 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800699 }
700 return Void();
701 }
702
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800703 virtual Return<void> onError(c2_hidl::Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800704 LOG(DEBUG) << "onError --"
705 << " status = " << s
706 << ", errorCode = " << errorCode
707 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800708 if (std::shared_ptr<Listener> listener = base.lock()) {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800709 listener->onError(component, s == c2_hidl::Status::OK ?
Pawin Vongmasa36653902018-11-15 00:10:25 -0800710 errorCode : static_cast<c2_status_t>(s));
711 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800712 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800713 }
714 return Void();
715 }
716
717 virtual Return<void> onFramesRendered(
718 const hidl_vec<RenderedFrame>& renderedFrames) override {
719 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800720 if (!listener) {
721 LOG(DEBUG) << "onFramesRendered -- listener died.";
722 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800723 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800724 for (const RenderedFrame& renderedFrame : renderedFrames) {
725 listener->onFrameRendered(
726 renderedFrame.bufferQueueId,
727 renderedFrame.slotId,
728 renderedFrame.timestampNs);
729 }
730 return Void();
731 }
732
733 virtual Return<void> onInputBuffersReleased(
734 const hidl_vec<InputBuffer>& inputBuffers) override {
735 std::shared_ptr<Listener> listener = base.lock();
736 if (!listener) {
737 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
738 return Void();
739 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800740 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800741 LOG(VERBOSE) << "onInputBuffersReleased --"
742 " received death notification of"
743 " input buffer:"
744 " frameIndex = " << inputBuffer.frameIndex
745 << ", bufferIndex = " << inputBuffer.arrayIndex
746 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -0800747 listener->onInputBufferDone(
748 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800749 }
750 return Void();
751 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800752
Pawin Vongmasa36653902018-11-15 00:10:25 -0800753};
754
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700755// Codec2Client::Component::BufferPoolSender
756struct Codec2Client::Component::BufferPoolSender :
757 hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
758 BufferPoolSender()
759 : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
760 }
761};
762
763// Codec2Client::Component::OutputBufferQueue
764struct Codec2Client::Component::OutputBufferQueue :
Sungtak Leea714f112021-03-16 05:40:03 -0700765 hardware::media::c2::OutputBufferQueue {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700766 OutputBufferQueue()
Sungtak Leea714f112021-03-16 05:40:03 -0700767 : hardware::media::c2::OutputBufferQueue() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700768 }
769};
770
Pawin Vongmasa36653902018-11-15 00:10:25 -0800771// Codec2Client
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700772Codec2Client::Codec2Client(sp<Base> const& base,
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700773 size_t serviceIndex)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800774 : Configurable{
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800775 [base]() -> sp<c2_hidl::IConfigurable> {
776 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800777 base->getConfigurable();
778 return transResult.isOk() ?
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800779 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800780 nullptr;
781 }()
782 },
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700783 mBase1_0{base},
784 mBase1_1{Base1_1::castFrom(base)},
Sungtak Lee8577dab2021-03-12 02:25:50 -0800785 mBase1_2{Base1_2::castFrom(base)},
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700786 mServiceIndex{serviceIndex} {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800787 Return<sp<bufferpool_hidl::IClientManager>> transResult = base->getPoolClientManager();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800788 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800789 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800790 } else {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800791 mHostPoolManager = static_cast<sp<bufferpool_hidl::IClientManager>>(transResult);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800792 }
793}
794
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700795sp<Codec2Client::Base> const& Codec2Client::getBase() const {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700796 return mBase1_0;
797}
798
799sp<Codec2Client::Base1_0> const& Codec2Client::getBase1_0() const {
800 return mBase1_0;
801}
802
803sp<Codec2Client::Base1_1> const& Codec2Client::getBase1_1() const {
804 return mBase1_1;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700805}
806
Sungtak Lee8577dab2021-03-12 02:25:50 -0800807sp<Codec2Client::Base1_2> const& Codec2Client::getBase1_2() const {
808 return mBase1_2;
809}
810
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700811std::string const& Codec2Client::getServiceName() const {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700812 return GetServiceNames()[mServiceIndex];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700813}
814
Pawin Vongmasa36653902018-11-15 00:10:25 -0800815c2_status_t Codec2Client::createComponent(
816 const C2String& name,
817 const std::shared_ptr<Codec2Client::Listener>& listener,
818 std::shared_ptr<Codec2Client::Component>* const component) {
819
Pawin Vongmasa36653902018-11-15 00:10:25 -0800820 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800821 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800822 hidlListener->base = listener;
Sungtak Lee8577dab2021-03-12 02:25:50 -0800823 Return<void> transStatus;
824 if (mBase1_2) {
825 transStatus = mBase1_2->createComponent_1_2(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800826 name,
827 hidlListener,
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800828 bufferpool_hidl::implementation::ClientManager::getInstance(),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800829 [&status, component, hidlListener](
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800830 c2_hidl::Status s,
831 const sp<c2_hidl::IComponent>& c) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800832 status = static_cast<c2_status_t>(s);
833 if (status != C2_OK) {
834 return;
835 }
836 *component = std::make_shared<Codec2Client::Component>(c);
837 hidlListener->component = *component;
Sungtak Lee8577dab2021-03-12 02:25:50 -0800838 });
839 }
840 else if (mBase1_1) {
841 transStatus = mBase1_1->createComponent_1_1(
842 name,
843 hidlListener,
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800844 bufferpool_hidl::implementation::ClientManager::getInstance(),
Sungtak Lee8577dab2021-03-12 02:25:50 -0800845 [&status, component, hidlListener](
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800846 c2_hidl::Status s,
847 const sp<c2_hidl_base::V1_1::IComponent>& c) {
Sungtak Lee8577dab2021-03-12 02:25:50 -0800848 status = static_cast<c2_status_t>(s);
849 if (status != C2_OK) {
850 return;
851 }
852 *component = std::make_shared<Codec2Client::Component>(c);
853 hidlListener->component = *component;
854 });
855 } else if (mBase1_0) { // ver1_0
856 transStatus = mBase1_0->createComponent(
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700857 name,
858 hidlListener,
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800859 bufferpool_hidl::implementation::ClientManager::getInstance(),
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700860 [&status, component, hidlListener](
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800861 c2_hidl::Status s,
862 const sp<c2_hidl_base::V1_0::IComponent>& c) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700863 status = static_cast<c2_status_t>(s);
864 if (status != C2_OK) {
865 return;
866 }
867 *component = std::make_shared<Codec2Client::Component>(c);
868 hidlListener->component = *component;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800869 });
Sungtak Lee8577dab2021-03-12 02:25:50 -0800870 } else {
871 status = C2_CORRUPTED;
872 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800873 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800874 LOG(ERROR) << "createComponent(" << name.c_str()
875 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800876 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800877 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800878 if (status == C2_NOT_FOUND) {
879 LOG(VERBOSE) << "createComponent(" << name.c_str()
880 << ") -- component not found.";
881 } else {
882 LOG(ERROR) << "createComponent(" << name.c_str()
883 << ") -- call failed: " << status << ".";
884 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800885 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800886 } else if (!*component) {
887 LOG(ERROR) << "createComponent(" << name.c_str()
888 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800889 return C2_CORRUPTED;
890 }
891
892 status = (*component)->setDeathListener(*component, listener);
893 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800894 LOG(ERROR) << "createComponent(" << name.c_str()
895 << ") -- failed to set up death listener: "
896 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800897 }
898
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700899 (*component)->mBufferPoolSender->setReceiver(mHostPoolManager);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800900 return status;
901}
902
903c2_status_t Codec2Client::createInterface(
904 const C2String& name,
905 std::shared_ptr<Codec2Client::Interface>* const interface) {
906 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700907 Return<void> transStatus = mBase1_0->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800908 name,
909 [&status, interface](
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800910 c2_hidl::Status s,
911 const sp<c2_hidl::IComponentInterface>& i) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800912 status = static_cast<c2_status_t>(s);
913 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800914 return;
915 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800916 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800917 });
918 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800919 LOG(ERROR) << "createInterface(" << name.c_str()
920 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800921 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800922 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800923 if (status == C2_NOT_FOUND) {
924 LOG(VERBOSE) << "createInterface(" << name.c_str()
925 << ") -- component not found.";
926 } else {
927 LOG(ERROR) << "createInterface(" << name.c_str()
928 << ") -- call failed: " << status << ".";
929 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800930 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800931 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800932
Pawin Vongmasa36653902018-11-15 00:10:25 -0800933 return status;
934}
935
936c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800937 std::shared_ptr<InputSurface>* const inputSurface) {
938 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700939 Return<void> transStatus = mBase1_0->createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800940 [&status, inputSurface](
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800941 c2_hidl::Status s,
942 const sp<c2_hidl::IInputSurface>& i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800943 status = static_cast<c2_status_t>(s);
944 if (status != C2_OK) {
945 return;
946 }
947 *inputSurface = std::make_shared<InputSurface>(i);
948 });
949 if (!transStatus.isOk()) {
950 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800951 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800952 } else if (status != C2_OK) {
953 LOG(DEBUG) << "createInputSurface -- call failed: "
954 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800955 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800956 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800957}
958
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700959std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
960 return Cache::List()[mServiceIndex].getTraits();
961}
962
963std::vector<C2Component::Traits> Codec2Client::_listComponents(
964 bool* success) const {
965 std::vector<C2Component::Traits> traits;
966 std::string const& serviceName = getServiceName();
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700967 Return<void> transStatus = mBase1_0->listComponents(
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800968 [&traits, &serviceName](c2_hidl::Status s,
969 const hidl_vec<c2_hidl::IComponentStore::ComponentTraits>& t) {
970 if (s != c2_hidl::Status::OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700971 LOG(DEBUG) << "_listComponents -- call failed: "
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800972 << static_cast<c2_status_t>(s) << ".";
973 return;
974 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700975 traits.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800976 for (size_t i = 0; i < t.size(); ++i) {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -0800977 if (!c2_hidl::utils::objcpy(&traits[i], t[i])) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700978 LOG(ERROR) << "_listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800979 return;
980 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700981 traits[i].owner = serviceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800982 }
983 });
984 if (!transStatus.isOk()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700985 LOG(ERROR) << "_listComponents -- transaction failed.";
986 *success = false;
987 } else {
988 *success = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800989 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700990 return traits;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800991}
992
993c2_status_t Codec2Client::copyBuffer(
994 const std::shared_ptr<C2Buffer>& src,
995 const std::shared_ptr<C2Buffer>& dst) {
996 // TODO: Implement?
997 (void)src;
998 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800999 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001000 return C2_OMITTED;
1001}
1002
1003std::shared_ptr<C2ParamReflector>
1004 Codec2Client::getParamReflector() {
1005 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
1006 // should reflect the HAL API.
1007 struct SimpleParamReflector : public C2ParamReflector {
1008 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001009 hidl_vec<c2_hidl::ParamIndex> indices(1);
1010 indices[0] = static_cast<c2_hidl::ParamIndex>(coreIndex.coreIndex());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001011 std::unique_ptr<C2StructDescriptor> descriptor;
1012 Return<void> transStatus = mBase->getStructDescriptors(
1013 indices,
1014 [&descriptor](
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001015 c2_hidl::Status s,
1016 const hidl_vec<c2_hidl::StructDescriptor>& sd) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001017 c2_status_t status = static_cast<c2_status_t>(s);
1018 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001019 LOG(DEBUG) << "SimpleParamReflector -- "
1020 "getStructDescriptors() failed: "
1021 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001022 descriptor.reset();
1023 return;
1024 }
1025 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001026 LOG(DEBUG) << "SimpleParamReflector -- "
1027 "getStructDescriptors() "
1028 "returned vector of size "
1029 << sd.size() << ". "
1030 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001031 descriptor.reset();
1032 return;
1033 }
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001034 if (!c2_hidl::utils::objcpy(&descriptor, sd[0])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001035 LOG(DEBUG) << "SimpleParamReflector -- "
1036 "getStructDescriptors() returned "
1037 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001038 descriptor.reset();
1039 return;
1040 }
1041 });
Wonsik Kim492fecd2020-11-19 11:14:11 -08001042 if (!transStatus.isOk()) {
1043 LOG(DEBUG) << "SimpleParamReflector -- transaction failed: "
1044 << transStatus.description();
1045 descriptor.reset();
1046 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001047 return descriptor;
1048 }
1049
1050 SimpleParamReflector(sp<Base> base)
1051 : mBase(base) { }
1052
1053 sp<Base> mBase;
1054 };
1055
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001056 return std::make_shared<SimpleParamReflector>(mBase1_0);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001057};
1058
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001059std::vector<std::string> const& Codec2Client::GetServiceNames() {
1060 static std::vector<std::string> sServiceNames{[]() {
1061 using ::android::hardware::media::c2::V1_0::IComponentStore;
1062 using ::android::hidl::manager::V1_2::IServiceManager;
1063
1064 while (true) {
1065 sp<IServiceManager> serviceManager = IServiceManager::getService();
1066 CHECK(serviceManager) << "Hardware service manager is not running.";
1067
1068 // There are three categories of services based on names.
1069 std::vector<std::string> defaultNames; // Prefixed with "default"
1070 std::vector<std::string> vendorNames; // Prefixed with "vendor"
1071 std::vector<std::string> otherNames; // Others
1072 Return<void> transResult;
1073 transResult = serviceManager->listManifestByInterface(
1074 IComponentStore::descriptor,
1075 [&defaultNames, &vendorNames, &otherNames](
1076 hidl_vec<hidl_string> const& instanceNames) {
1077 for (hidl_string const& instanceName : instanceNames) {
1078 char const* name = instanceName.c_str();
1079 if (strncmp(name, "default", 7) == 0) {
1080 defaultNames.emplace_back(name);
1081 } else if (strncmp(name, "vendor", 6) == 0) {
1082 vendorNames.emplace_back(name);
1083 } else {
1084 otherNames.emplace_back(name);
1085 }
1086 }
1087 });
1088 if (transResult.isOk()) {
1089 // Sort service names in each category.
1090 std::sort(defaultNames.begin(), defaultNames.end());
1091 std::sort(vendorNames.begin(), vendorNames.end());
1092 std::sort(otherNames.begin(), otherNames.end());
1093
1094 // Concatenate the three lists in this order: default, vendor,
1095 // other.
1096 std::vector<std::string>& names = defaultNames;
1097 names.reserve(names.size() + vendorNames.size() + otherNames.size());
1098 names.insert(names.end(),
1099 std::make_move_iterator(vendorNames.begin()),
1100 std::make_move_iterator(vendorNames.end()));
1101 names.insert(names.end(),
1102 std::make_move_iterator(otherNames.begin()),
1103 std::make_move_iterator(otherNames.end()));
1104
1105 // Summarize to logcat.
1106 if (names.empty()) {
1107 LOG(INFO) << "No Codec2 services declared in the manifest.";
1108 } else {
1109 std::stringstream stringOutput;
1110 stringOutput << "Available Codec2 services:";
1111 for (std::string const& name : names) {
1112 stringOutput << " \"" << name << "\"";
1113 }
1114 LOG(INFO) << stringOutput.str();
1115 }
1116
1117 return names;
1118 }
1119 LOG(ERROR) << "Could not retrieve the list of service instances of "
1120 << IComponentStore::descriptor
1121 << ". Retrying...";
1122 }
1123 }()};
1124 return sServiceNames;
1125}
1126
Pawin Vongmasa36653902018-11-15 00:10:25 -08001127std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa83d2c552020-03-05 04:36:08 -08001128 const char* name,
1129 bool setAsPreferredCodec2ComponentStore) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001130 size_t index = getServiceIndex(name);
Pawin Vongmasa83d2c552020-03-05 04:36:08 -08001131 if (index == GetServiceNames().size()) {
1132 if (setAsPreferredCodec2ComponentStore) {
1133 LOG(WARNING) << "CreateFromService(" << name
1134 << ") -- preferred C2ComponentStore not set.";
1135 }
1136 return nullptr;
1137 }
1138 std::shared_ptr<Codec2Client> client = _CreateFromIndex(index);
1139 if (setAsPreferredCodec2ComponentStore) {
1140 SetPreferredCodec2ComponentStore(
1141 std::make_shared<Client2Store>(client));
1142 LOG(INFO) << "CreateFromService(" << name
1143 << ") -- service set as preferred C2ComponentStore.";
1144 }
1145 return client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001146}
1147
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001148std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
1149 CreateFromAllServices() {
1150 std::vector<std::shared_ptr<Codec2Client>> clients(
1151 GetServiceNames().size());
1152 for (size_t i = GetServiceNames().size(); i > 0; ) {
1153 --i;
1154 clients[i] = _CreateFromIndex(i);
1155 }
1156 return clients;
1157}
1158
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001159std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001160 std::string const& name = GetServiceNames()[index];
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08001161 LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001162 sp<Base> baseStore = Base::getService(name);
1163 CHECK(baseStore) << "Codec2 service \"" << name << "\""
1164 " inaccessible for unknown reasons.";
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08001165 LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001166 return std::make_shared<Codec2Client>(baseStore, index);
1167}
1168
1169c2_status_t Codec2Client::ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001170 const std::string &key,
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001171 size_t numberOfAttempts,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001172 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
1173 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001174 c2_status_t status = C2_NO_INIT; // no IComponentStores present
1175
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001176 // Cache the mapping key -> index of Codec2Client in Cache::List().
Pawin Vongmasa36653902018-11-15 00:10:25 -08001177 static std::mutex key2IndexMutex;
1178 static std::map<std::string, size_t> key2Index;
1179
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001180 // By default try all stores. However, try the last known client first. If
1181 // the last known client fails, retry once. We do this by pushing the last
1182 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -08001183 std::deque<size_t> indices;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001184 for (size_t index = Cache::List().size(); index > 0; ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001185 indices.push_front(--index);
1186 }
1187
1188 bool wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001189 {
1190 std::scoped_lock lock{key2IndexMutex};
1191 auto it = key2Index.find(key);
1192 if (it != key2Index.end()) {
1193 indices.push_front(it->second);
1194 wasMapped = true;
1195 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001196 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001197
1198 for (size_t index : indices) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001199 Cache& cache = Cache::List()[index];
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001200 for (size_t tries = numberOfAttempts; tries > 0; --tries) {
1201 std::shared_ptr<Codec2Client> client{cache.getClient()};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001202 status = predicate(client);
1203 if (status == C2_OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001204 std::scoped_lock lock{key2IndexMutex};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001205 key2Index[key] = index; // update last known client index
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001206 return C2_OK;
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001207 } else if (status == C2_NO_MEMORY) {
1208 return C2_NO_MEMORY;
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001209 } else if (status == C2_TRANSACTION_FAILED) {
1210 LOG(WARNING) << "\"" << key << "\" failed for service \""
1211 << client->getName()
1212 << "\" due to transaction failure. "
1213 << "(Service may have crashed.)"
1214 << (tries > 1 ? " Retrying..." : "");
1215 cache.invalidate();
1216 continue;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001217 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001218 if (wasMapped) {
1219 LOG(INFO) << "\"" << key << "\" became invalid in service \""
1220 << client->getName() << "\". Retrying...";
1221 wasMapped = false;
1222 }
1223 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001224 }
1225 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001226 return status; // return the last status from a valid client
Pawin Vongmasa36653902018-11-15 00:10:25 -08001227}
1228
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001229c2_status_t Codec2Client::CreateComponentByName(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001230 const char* componentName,
1231 const std::shared_ptr<Listener>& listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001232 std::shared_ptr<Component>* component,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001233 std::shared_ptr<Codec2Client>* owner,
1234 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001235 std::string key{"create:"};
1236 key.append(componentName);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001237 c2_status_t status = ForAllServices(
1238 key,
1239 numberOfAttempts,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001240 [owner, component, componentName, &listener](
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001241 const std::shared_ptr<Codec2Client> &client)
1242 -> c2_status_t {
1243 c2_status_t status = client->createComponent(componentName,
1244 listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001245 component);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001246 if (status == C2_OK) {
1247 if (owner) {
1248 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001249 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001250 } else if (status != C2_NOT_FOUND) {
1251 LOG(DEBUG) << "IComponentStore("
1252 << client->getServiceName()
1253 << ")::createComponent(\"" << componentName
1254 << "\") returned status = "
1255 << status << ".";
1256 }
1257 return status;
1258 });
1259 if (status != C2_OK) {
1260 LOG(DEBUG) << "Failed to create component \"" << componentName
1261 << "\" from all known services. "
1262 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001263 }
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001264 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001265}
1266
1267std::shared_ptr<Codec2Client::Interface>
1268 Codec2Client::CreateInterfaceByName(
1269 const char* interfaceName,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001270 std::shared_ptr<Codec2Client>* owner,
1271 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001272 std::string key{"create:"};
1273 key.append(interfaceName);
1274 std::shared_ptr<Interface> interface;
1275 c2_status_t status = ForAllServices(
1276 key,
1277 numberOfAttempts,
1278 [owner, &interface, interfaceName](
1279 const std::shared_ptr<Codec2Client> &client)
1280 -> c2_status_t {
1281 c2_status_t status = client->createInterface(interfaceName,
1282 &interface);
1283 if (status == C2_OK) {
1284 if (owner) {
1285 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001286 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001287 } else if (status != C2_NOT_FOUND) {
1288 LOG(DEBUG) << "IComponentStore("
1289 << client->getServiceName()
1290 << ")::createInterface(\"" << interfaceName
1291 << "\") returned status = "
1292 << status << ".";
1293 }
1294 return status;
1295 });
1296 if (status != C2_OK) {
1297 LOG(DEBUG) << "Failed to create interface \"" << interfaceName
1298 << "\" from all known services. "
1299 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001300 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001301 return interface;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001302}
1303
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001304std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
1305 static std::vector<C2Component::Traits> sList{[]() {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001306 std::vector<C2Component::Traits> list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001307 for (Cache& cache : Cache::List()) {
1308 std::vector<C2Component::Traits> const& traits = cache.getTraits();
1309 list.insert(list.end(), traits.begin(), traits.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001310 }
1311 return list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001312 }()};
1313 return sList;
1314}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001315
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001316std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
1317 char const* serviceName) {
Pawin Vongmasa18588322019-05-18 01:52:13 -07001318 int32_t inputSurfaceSetting = ::android::base::GetIntProperty(
1319 "debug.stagefright.c2inputsurface", int32_t(0));
1320 if (inputSurfaceSetting <= 0) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001321 return nullptr;
1322 }
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001323 size_t index = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001324 if (serviceName) {
1325 index = getServiceIndex(serviceName);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001326 if (index == GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001327 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
1328 << serviceName << "\"";
1329 }
1330 }
1331
1332 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001333 if (index != GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001334 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
1335 if (client->createInputSurface(&inputSurface) == C2_OK) {
1336 return inputSurface;
1337 }
1338 }
1339 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
1340 "from all services...";
1341 for (Cache& cache : Cache::List()) {
1342 std::shared_ptr<Codec2Client> client = cache.getClient();
1343 if (client->createInputSurface(&inputSurface) == C2_OK) {
1344 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
1345 "service \"" << client->getServiceName() << "\"";
1346 return inputSurface;
1347 }
1348 }
1349 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
1350 "from all services";
1351 return nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001352}
1353
1354// Codec2Client::Listener
1355
1356Codec2Client::Listener::~Listener() {
1357}
1358
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001359// Codec2Client::Interface
1360Codec2Client::Interface::Interface(const sp<Base>& base)
1361 : Configurable{
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001362 [base]() -> sp<c2_hidl::IConfigurable> {
1363 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001364 base->getConfigurable();
1365 return transResult.isOk() ?
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001366 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001367 nullptr;
1368 }()
1369 },
1370 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001371}
1372
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001373// Codec2Client::Component
1374Codec2Client::Component::Component(const sp<Base>& base)
1375 : Configurable{
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001376 [base]() -> sp<c2_hidl::IConfigurable> {
1377 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001378 base->getInterface();
1379 if (!transResult1.isOk()) {
1380 return nullptr;
1381 }
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001382 Return<sp<c2_hidl::IConfigurable>> transResult2 =
1383 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001384 getConfigurable();
1385 return transResult2.isOk() ?
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001386 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001387 nullptr;
1388 }()
1389 },
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001390 mBase1_0{base},
1391 mBase1_1{Base1_1::castFrom(base)},
Sungtak Lee8577dab2021-03-12 02:25:50 -08001392 mBase1_2{Base1_2::castFrom(base)},
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001393 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1394 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1395}
1396
1397Codec2Client::Component::Component(const sp<Base1_1>& base)
1398 : Configurable{
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001399 [base]() -> sp<c2_hidl::IConfigurable> {
1400 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001401 base->getInterface();
1402 if (!transResult1.isOk()) {
1403 return nullptr;
1404 }
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001405 Return<sp<c2_hidl::IConfigurable>> transResult2 =
1406 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001407 getConfigurable();
1408 return transResult2.isOk() ?
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001409 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001410 nullptr;
1411 }()
1412 },
1413 mBase1_0{base},
1414 mBase1_1{base},
Sungtak Lee8577dab2021-03-12 02:25:50 -08001415 mBase1_2{Base1_2::castFrom(base)},
1416 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1417 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1418}
1419
1420Codec2Client::Component::Component(const sp<Base1_2>& base)
1421 : Configurable{
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001422 [base]() -> sp<c2_hidl::IConfigurable> {
1423 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Sungtak Lee8577dab2021-03-12 02:25:50 -08001424 base->getInterface();
1425 if (!transResult1.isOk()) {
1426 return nullptr;
1427 }
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001428 Return<sp<c2_hidl::IConfigurable>> transResult2 =
1429 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Sungtak Lee8577dab2021-03-12 02:25:50 -08001430 getConfigurable();
1431 return transResult2.isOk() ?
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001432 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Sungtak Lee8577dab2021-03-12 02:25:50 -08001433 nullptr;
1434 }()
1435 },
1436 mBase1_0{base},
1437 mBase1_1{base},
1438 mBase1_2{base},
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001439 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1440 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001441}
1442
1443Codec2Client::Component::~Component() {
1444}
1445
1446c2_status_t Codec2Client::Component::createBlockPool(
1447 C2Allocator::id_t id,
1448 C2BlockPool::local_id_t* blockPoolId,
1449 std::shared_ptr<Codec2Client::Configurable>* configurable) {
1450 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001451 Return<void> transStatus = mBase1_0->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001452 static_cast<uint32_t>(id),
1453 [&status, blockPoolId, configurable](
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001454 c2_hidl::Status s,
Pawin Vongmasa36653902018-11-15 00:10:25 -08001455 uint64_t pId,
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001456 const sp<c2_hidl::IConfigurable>& c) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001457 status = static_cast<c2_status_t>(s);
1458 configurable->reset();
1459 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001460 LOG(DEBUG) << "createBlockPool -- call failed: "
1461 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001462 return;
1463 }
1464 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001465 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001466 });
1467 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001468 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001469 return C2_TRANSACTION_FAILED;
1470 }
1471 return status;
1472}
1473
1474c2_status_t Codec2Client::Component::destroyBlockPool(
1475 C2BlockPool::local_id_t localId) {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001476 Return<c2_hidl::Status> transResult = mBase1_0->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001477 static_cast<uint64_t>(localId));
1478 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001479 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001480 return C2_TRANSACTION_FAILED;
1481 }
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001482 return static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transResult));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001483}
1484
Wonsik Kimab34ed62019-01-31 15:28:46 -08001485void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001486 const std::list<std::unique_ptr<C2Work>> &workItems) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001487 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001488 mOutputBufferQueue->holdBufferQueueBlocks(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001489}
1490
1491c2_status_t Codec2Client::Component::queue(
1492 std::list<std::unique_ptr<C2Work>>* const items) {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001493 c2_hidl::WorkBundle workBundle;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001494 if (!objcpy(&workBundle, *items, mBufferPoolSender.get())) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001495 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001496 return C2_TRANSACTION_FAILED;
1497 }
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001498 Return<c2_hidl::Status> transStatus = mBase1_0->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001499 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001500 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001501 return C2_TRANSACTION_FAILED;
1502 }
1503 c2_status_t status =
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001504 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001505 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001506 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001507 }
1508 return status;
1509}
1510
1511c2_status_t Codec2Client::Component::flush(
1512 C2Component::flush_mode_t mode,
1513 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
1514 (void)mode; // Flush mode isn't supported in HIDL yet.
1515 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001516 Return<void> transStatus = mBase1_0->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001517 [&status, flushedWork](
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001518 c2_hidl::Status s, const c2_hidl::WorkBundle& wb) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001519 status = static_cast<c2_status_t>(s);
1520 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001521 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001522 return;
1523 }
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001524 if (!c2_hidl::utils::objcpy(flushedWork, wb)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001525 status = C2_CORRUPTED;
1526 } else {
1527 status = C2_OK;
1528 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001529 });
1530 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001531 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001532 return C2_TRANSACTION_FAILED;
1533 }
1534
1535 // Indices of flushed work items.
1536 std::vector<uint64_t> flushedIndices;
1537 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
1538 if (work) {
1539 if (work->worklets.empty()
1540 || !work->worklets.back()
1541 || (work->worklets.back()->output.flags &
1542 C2FrameData::FLAG_INCOMPLETE) == 0) {
1543 // input is complete
1544 flushedIndices.emplace_back(
1545 work->input.ordinal.frameIndex.peeku());
1546 }
1547 }
1548 }
1549
Pawin Vongmasa36653902018-11-15 00:10:25 -08001550 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001551 mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001552
1553 return status;
1554}
1555
1556c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001557 Return<c2_hidl::Status> transStatus = mBase1_0->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001558 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1559 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001560 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001561 return C2_TRANSACTION_FAILED;
1562 }
1563 c2_status_t status =
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001564 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001565 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001566 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001567 }
1568 return status;
1569}
1570
1571c2_status_t Codec2Client::Component::start() {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001572 Return<c2_hidl::Status> transStatus = mBase1_0->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001573 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001574 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001575 return C2_TRANSACTION_FAILED;
1576 }
1577 c2_status_t status =
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001578 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001579 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001580 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001581 }
1582 return status;
1583}
1584
1585c2_status_t Codec2Client::Component::stop() {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001586 Return<c2_hidl::Status> transStatus = mBase1_0->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001587 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001588 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001589 return C2_TRANSACTION_FAILED;
1590 }
1591 c2_status_t status =
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001592 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001593 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001594 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001595 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001596 return status;
1597}
1598
1599c2_status_t Codec2Client::Component::reset() {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001600 Return<c2_hidl::Status> transStatus = mBase1_0->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001601 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001602 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001603 return C2_TRANSACTION_FAILED;
1604 }
1605 c2_status_t status =
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001606 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001607 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001608 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001609 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001610 return status;
1611}
1612
1613c2_status_t Codec2Client::Component::release() {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001614 Return<c2_hidl::Status> transStatus = mBase1_0->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001615 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001616 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001617 return C2_TRANSACTION_FAILED;
1618 }
1619 c2_status_t status =
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001620 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001621 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001622 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001623 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001624 return status;
1625}
1626
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001627c2_status_t Codec2Client::Component::configureVideoTunnel(
1628 uint32_t avSyncHwId,
1629 native_handle_t** sidebandHandle) {
1630 *sidebandHandle = nullptr;
1631 if (!mBase1_1) {
1632 return C2_OMITTED;
1633 }
1634 c2_status_t status{};
1635 Return<void> transStatus = mBase1_1->configureVideoTunnel(avSyncHwId,
1636 [&status, sidebandHandle](
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001637 c2_hidl::Status s, hardware::hidl_handle const& h) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001638 status = static_cast<c2_status_t>(s);
1639 if (h.getNativeHandle()) {
1640 *sidebandHandle = native_handle_clone(h.getNativeHandle());
1641 }
1642 });
1643 if (!transStatus.isOk()) {
1644 LOG(ERROR) << "configureVideoTunnel -- transaction failed.";
1645 return C2_TRANSACTION_FAILED;
1646 }
1647 return status;
1648}
1649
Pawin Vongmasa36653902018-11-15 00:10:25 -08001650c2_status_t Codec2Client::Component::setOutputSurface(
1651 C2BlockPool::local_id_t blockPoolId,
1652 const sp<IGraphicBufferProducer>& surface,
Sungtak Leedb14cba2021-04-10 00:50:23 -07001653 uint32_t generation,
1654 int maxDequeueCount) {
Sungtak Lee08515812019-06-05 11:16:32 -07001655 uint64_t bqId = 0;
1656 sp<IGraphicBufferProducer> nullIgbp;
1657 sp<HGraphicBufferProducer2> nullHgbp;
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08001658
Sungtak Lee08515812019-06-05 11:16:32 -07001659 sp<HGraphicBufferProducer2> igbp = surface ?
1660 surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
1661 if (surface && !igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001662 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001663 }
1664
Sungtak Leefb579022022-05-10 06:36:15 +00001665 std::scoped_lock lock(mOutputMutex);
Sungtak Leea714f112021-03-16 05:40:03 -07001666 std::shared_ptr<SurfaceSyncObj> syncObj;
1667
Sungtak Lee08515812019-06-05 11:16:32 -07001668 if (!surface) {
Sungtak Leedb14cba2021-04-10 00:50:23 -07001669 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07001670 } else if (surface->getUniqueId(&bqId) != OK) {
1671 LOG(ERROR) << "setOutputSurface -- "
1672 "cannot obtain bufferqueue id.";
1673 bqId = 0;
Sungtak Leedb14cba2021-04-10 00:50:23 -07001674 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07001675 } else {
Sungtak Leedb14cba2021-04-10 00:50:23 -07001676 mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount, mBase1_2 ?
1677 &syncObj : nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07001678 }
Lajos Molnar78aa7c92021-02-18 21:39:01 -08001679
1680 // set consumer bits
1681 // TODO: should this get incorporated into setOutputSurface method so that consumer bits
1682 // can be set atomically?
1683 uint64_t consumerUsage = kDefaultConsumerUsage;
1684 {
1685 if (surface) {
1686 int usage = 0;
1687 status_t err = surface->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage);
1688 if (err != NO_ERROR) {
1689 ALOGD("setOutputSurface -- failed to get consumer usage bits (%d/%s). ignoring",
1690 err, asString(err));
1691 } else {
1692 // Note: we are adding the default usage because components must support
1693 // producing output frames that can be displayed an all output surfaces.
1694
1695 // TODO: do not set usage for tunneled scenario. It is unclear if consumer usage
1696 // is meaningful in a tunneled scenario; on one hand output buffers exist, but
1697 // they do not exist inside of C2 scope. Any buffer usage shall be communicated
1698 // through the sideband channel.
1699
1700 // do an unsigned conversion as bit-31 may be 1
1701 consumerUsage = (uint32_t)usage | kDefaultConsumerUsage;
1702 }
1703 }
1704
1705 C2StreamUsageTuning::output outputUsage{
1706 0u, C2AndroidMemoryUsage::FromGrallocUsage(consumerUsage).expected};
1707 std::vector<std::unique_ptr<C2SettingResult>> failures;
1708 c2_status_t err = config({&outputUsage}, C2_MAY_BLOCK, &failures);
1709 if (err != C2_OK) {
1710 ALOGD("setOutputSurface -- failed to set consumer usage (%d/%s)",
1711 err, asString(err));
1712 }
1713 }
1714 ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx%s",
1715 generation, (long long)consumerUsage, syncObj ? " sync" : "");
Sungtak Lee08515812019-06-05 11:16:32 -07001716
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001717 Return<c2_hidl::Status> transStatus = syncObj ?
Sungtak Leea714f112021-03-16 05:40:03 -07001718 mBase1_2->setOutputSurfaceWithSyncObj(
1719 static_cast<uint64_t>(blockPoolId),
1720 bqId == 0 ? nullHgbp : igbp, *syncObj) :
1721 mBase1_0->setOutputSurface(
1722 static_cast<uint64_t>(blockPoolId),
1723 bqId == 0 ? nullHgbp : igbp);
Lajos Molnar78aa7c92021-02-18 21:39:01 -08001724
Pawin Vongmasa36653902018-11-15 00:10:25 -08001725 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001726 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001727 return C2_TRANSACTION_FAILED;
1728 }
1729 c2_status_t status =
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001730 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001731 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001732 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001733 }
Sungtak Leea714f112021-03-16 05:40:03 -07001734 ALOGD("Surface configure completed");
Pawin Vongmasa36653902018-11-15 00:10:25 -08001735 return status;
1736}
1737
1738status_t Codec2Client::Component::queueToOutputSurface(
1739 const C2ConstGraphicBlock& block,
1740 const QueueBufferInput& input,
1741 QueueBufferOutput* output) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001742 return mOutputBufferQueue->outputBuffer(block, input, output);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001743}
1744
Sungtak Leea714f112021-03-16 05:40:03 -07001745void Codec2Client::Component::setOutputSurfaceMaxDequeueCount(
1746 int maxDequeueCount) {
1747 mOutputBufferQueue->updateMaxDequeueBufferCount(maxDequeueCount);
1748}
1749
Sungtak Leec7da7a02022-05-05 08:45:33 +00001750void Codec2Client::Component::stopUsingOutputSurface(
1751 C2BlockPool::local_id_t blockPoolId) {
Sungtak Leefb579022022-05-10 06:36:15 +00001752 std::scoped_lock lock(mOutputMutex);
Sungtak Leec7da7a02022-05-05 08:45:33 +00001753 mOutputBufferQueue->stop();
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001754 Return<c2_hidl::Status> transStatus = mBase1_0->setOutputSurface(
Sungtak Leec7da7a02022-05-05 08:45:33 +00001755 static_cast<uint64_t>(blockPoolId), nullptr);
1756 if (!transStatus.isOk()) {
1757 LOG(ERROR) << "setOutputSurface(stopUsingOutputSurface) -- transaction failed.";
1758 } else {
1759 c2_status_t status =
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001760 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Sungtak Leec7da7a02022-05-05 08:45:33 +00001761 if (status != C2_OK) {
1762 LOG(DEBUG) << "setOutputSurface(stopUsingOutputSurface) -- call failed: "
1763 << status << ".";
1764 }
1765 }
1766}
1767
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001768c2_status_t Codec2Client::Component::connectToInputSurface(
1769 const std::shared_ptr<InputSurface>& inputSurface,
1770 std::shared_ptr<InputSurfaceConnection>* connection) {
1771 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001772 Return<void> transStatus = mBase1_0->connectToInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001773 inputSurface->mBase,
1774 [&status, connection](
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001775 c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001776 status = static_cast<c2_status_t>(s);
1777 if (status != C2_OK) {
1778 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1779 << status << ".";
1780 return;
1781 }
1782 *connection = std::make_shared<InputSurfaceConnection>(c);
1783 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001784 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001785 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001786 return C2_TRANSACTION_FAILED;
1787 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001788 return status;
1789}
1790
1791c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001792 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001793 const sp<HGraphicBufferSource>& source,
1794 std::shared_ptr<InputSurfaceConnection>* connection) {
1795 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001796 Return<void> transStatus = mBase1_0->connectToOmxInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001797 producer, source,
1798 [&status, connection](
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001799 c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001800 status = static_cast<c2_status_t>(s);
1801 if (status != C2_OK) {
1802 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1803 << status << ".";
1804 return;
1805 }
1806 *connection = std::make_shared<InputSurfaceConnection>(c);
1807 });
1808 if (!transStatus.isOk()) {
1809 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1810 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001811 }
1812 return status;
1813}
1814
1815c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001816 Return<c2_hidl::Status> transStatus = mBase1_0->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001817 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001818 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001819 return C2_TRANSACTION_FAILED;
1820 }
1821 c2_status_t status =
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001822 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001823 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001824 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1825 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001826 }
1827 return status;
1828}
1829
1830c2_status_t Codec2Client::Component::setDeathListener(
1831 const std::shared_ptr<Component>& component,
1832 const std::shared_ptr<Listener>& listener) {
1833
1834 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1835 std::weak_ptr<Component> component;
1836 std::weak_ptr<Listener> base;
1837
1838 virtual void serviceDied(
1839 uint64_t /* cookie */,
1840 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1841 ) override {
1842 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1843 listener->onDeath(component);
1844 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001845 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001846 }
1847 }
1848 };
1849
1850 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1851 deathRecipient->base = listener;
1852 deathRecipient->component = component;
1853
1854 component->mDeathRecipient = deathRecipient;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001855 Return<bool> transResult = component->mBase1_0->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001856 component->mDeathRecipient, 0);
1857 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001858 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001859 return C2_TRANSACTION_FAILED;
1860 }
1861 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001862 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001863 return C2_CORRUPTED;
1864 }
1865 return C2_OK;
1866}
1867
1868// Codec2Client::InputSurface
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001869Codec2Client::InputSurface::InputSurface(const sp<c2_hidl::IInputSurface>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001870 : Configurable{
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001871 [base]() -> sp<c2_hidl::IConfigurable> {
1872 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001873 base->getConfigurable();
1874 return transResult.isOk() ?
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001875 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001876 nullptr;
1877 }()
1878 },
1879 mBase{base},
1880 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001881 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
1882 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001883 base->getGraphicBufferProducer();
1884 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001885 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001886 nullptr;
1887 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001888}
1889
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001890sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08001891 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1892 return mGraphicBufferProducer;
1893}
1894
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001895sp<c2_hidl::IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001896 return mBase;
1897}
1898
1899// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08001900Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001901 const sp<c2_hidl::IInputSurfaceConnection>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001902 : Configurable{
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001903 [base]() -> sp<c2_hidl::IConfigurable> {
1904 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001905 base->getConfigurable();
1906 return transResult.isOk() ?
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001907 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001908 nullptr;
1909 }()
1910 },
1911 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001912}
1913
1914c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Wonsik Kimfdf5f1b2022-12-07 10:28:30 -08001915 Return<c2_hidl::Status> transResult = mBase->disconnect();
1916 return static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transResult));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001917}
1918
1919} // namespace android