blob: b0ce733286345b9a9eb036ffb5f3be38a4c9aef7 [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 Kimc8fc2c32022-12-12 14:43:00 -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 Kimc8fc2c32022-12-12 14:43:00 -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>
Wonsik Kim1caded02022-12-09 13:03:11 -080047#include <codec2/aidl/ParamTypes.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070048#include <codec2/hidl/1.0/types.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070049#include <codec2/hidl/1.1/types.h>
Sungtak Lee8577dab2021-03-12 02:25:50 -080050#include <codec2/hidl/1.2/types.h>
Sungtak Leea714f112021-03-16 05:40:03 -070051#include <codec2/hidl/output.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070052
53#include <cutils/native_handle.h>
54#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
55#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
Lajos Molnar78aa7c92021-02-18 21:39:01 -080056#include <hardware/gralloc.h> // for GRALLOC_USAGE_*
Pawin Vongmasabf69de92019-10-29 06:21:27 -070057#include <hidl/HidlSupport.h>
Lajos Molnar78aa7c92021-02-18 21:39:01 -080058#include <system/window.h> // for NATIVE_WINDOW_QUERY_*
59#include <media/stagefright/foundation/ADebug.h> // for asString(status_t)
Pawin Vongmasa36653902018-11-15 00:10:25 -080060
61#include <deque>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070062#include <iterator>
Pawin Vongmasa36653902018-11-15 00:10:25 -080063#include <limits>
64#include <map>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070065#include <mutex>
66#include <sstream>
67#include <thread>
Pawin Vongmasa36653902018-11-15 00:10:25 -080068#include <type_traits>
69#include <vector>
70
Pawin Vongmasa36653902018-11-15 00:10:25 -080071namespace android {
72
73using ::android::hardware::hidl_vec;
74using ::android::hardware::hidl_string;
75using ::android::hardware::Return;
76using ::android::hardware::Void;
Pawin Vongmasa36653902018-11-15 00:10:25 -080077
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080078using HGraphicBufferProducer1 = ::android::hardware::graphics::bufferqueue::
79 V1_0::IGraphicBufferProducer;
80using HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
81 V2_0::IGraphicBufferProducer;
82using B2HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
83 V2_0::utils::B2HGraphicBufferProducer;
84using H2BGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
85 V2_0::utils::H2BGraphicBufferProducer;
Sungtak Leea714f112021-03-16 05:40:03 -070086using ::android::hardware::media::c2::V1_2::SurfaceSyncObj;
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080087
Wonsik Kimc8fc2c32022-12-12 14:43:00 -080088namespace bufferpool_hidl = ::android::hardware::media::bufferpool::V2_0;
89namespace c2_aidl = ::aidl::android::hardware::media::c2;
90namespace c2_hidl_base = ::android::hardware::media::c2;
91namespace c2_hidl = ::android::hardware::media::c2::V1_2;
92
93using c2_hidl::utils::operator<<;
94
Pawin Vongmasa36653902018-11-15 00:10:25 -080095namespace /* unnamed */ {
96
97// c2_status_t value that corresponds to hwbinder transaction failure.
98constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
99
Lajos Molnar78aa7c92021-02-18 21:39:01 -0800100// By default prepare buffer to be displayed on any of the common surfaces
101constexpr uint64_t kDefaultConsumerUsage =
102 (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER);
103
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700104// Searches for a name in GetServiceNames() and returns the index found. If the
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700105// name is not found, the returned index will be equal to
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700106// GetServiceNames().size().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700107size_t getServiceIndex(char const* name) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700108 std::vector<std::string> const& names = Codec2Client::GetServiceNames();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700109 size_t i = 0;
110 for (; i < names.size(); ++i) {
111 if (name == names[i]) {
112 break;
113 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800114 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700115 return i;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800116}
117
Pawin Vongmasa83d2c552020-03-05 04:36:08 -0800118class Client2Store : public C2ComponentStore {
119 std::shared_ptr<Codec2Client> mClient;
120
121public:
122 Client2Store(std::shared_ptr<Codec2Client> const& client)
123 : mClient(client) { }
124
125 virtual ~Client2Store() = default;
126
127 virtual c2_status_t config_sm(
128 std::vector<C2Param*> const &params,
129 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
130 return mClient->config(params, C2_MAY_BLOCK, failures);
131 };
132
133 virtual c2_status_t copyBuffer(
134 std::shared_ptr<C2GraphicBuffer>,
135 std::shared_ptr<C2GraphicBuffer>) {
136 return C2_OMITTED;
137 }
138
139 virtual c2_status_t createComponent(
140 C2String, std::shared_ptr<C2Component>* const component) {
141 component->reset();
142 return C2_OMITTED;
143 }
144
145 virtual c2_status_t createInterface(
146 C2String, std::shared_ptr<C2ComponentInterface>* const interface) {
147 interface->reset();
148 return C2_OMITTED;
149 }
150
151 virtual c2_status_t query_sm(
152 std::vector<C2Param*> const& stackParams,
153 std::vector<C2Param::Index> const& heapParamIndices,
154 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
155 return mClient->query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
156 }
157
158 virtual c2_status_t querySupportedParams_nb(
159 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
160 return mClient->querySupportedParams(params);
161 }
162
163 virtual c2_status_t querySupportedValues_sm(
164 std::vector<C2FieldSupportedValuesQuery>& fields) const {
165 return mClient->querySupportedValues(fields, C2_MAY_BLOCK);
166 }
167
168 virtual C2String getName() const {
169 return mClient->getName();
170 }
171
172 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const {
173 return mClient->getParamReflector();
174 }
175
176 virtual std::vector<std::shared_ptr<C2Component::Traits const>> listComponents() {
177 return std::vector<std::shared_ptr<C2Component::Traits const>>();
178 }
179};
180
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700181} // unnamed namespace
182
183// This class caches a Codec2Client object and its component traits. The client
184// will be created the first time it is needed, and it can be refreshed if the
185// service dies (by calling invalidate()). The first time listComponents() is
186// called from the client, the result will be cached.
187class Codec2Client::Cache {
188 // Cached client
189 std::shared_ptr<Codec2Client> mClient;
190 mutable std::mutex mClientMutex;
191
192 // Cached component traits
193 std::vector<C2Component::Traits> mTraits;
194 std::once_flag mTraitsInitializationFlag;
195
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700196 // The index of the service. This is based on GetServiceNames().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700197 size_t mIndex;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700198 // Called by s() exactly once to initialize the cache. The index must be a
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700199 // valid index into the vector returned by GetServiceNames(). Calling
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700200 // init(index) will associate the cache to the service with name
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700201 // GetServiceNames()[index].
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700202 void init(size_t index) {
203 mIndex = index;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700204 }
205
206public:
207 Cache() = default;
208
209 // Initializes mClient if needed, then returns mClient.
210 // If the service is unavailable but listed in the manifest, this function
211 // will block indefinitely.
212 std::shared_ptr<Codec2Client> getClient() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700213 std::scoped_lock lock{mClientMutex};
214 if (!mClient) {
215 mClient = Codec2Client::_CreateFromIndex(mIndex);
216 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700217 CHECK(mClient) << "Failed to create Codec2Client to service \""
218 << GetServiceNames()[mIndex] << "\". (Index = "
219 << mIndex << ").";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700220 return mClient;
221 }
222
223 // Causes a subsequent call to getClient() to create a new client. This
224 // function should be called after the service dies.
225 //
226 // Note: This function is called only by ForAllServices().
227 void invalidate() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700228 std::scoped_lock lock{mClientMutex};
229 mClient = nullptr;
230 }
231
232 // Returns a list of traits for components supported by the service. This
233 // list is cached.
234 std::vector<C2Component::Traits> const& getTraits() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700235 std::call_once(mTraitsInitializationFlag, [this]() {
236 bool success{false};
237 // Spin until _listComponents() is successful.
238 while (true) {
239 std::shared_ptr<Codec2Client> client = getClient();
240 mTraits = client->_listComponents(&success);
241 if (success) {
242 break;
243 }
Pawin Vongmasa21617db2020-04-24 06:16:42 -0700244 invalidate();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700245 using namespace std::chrono_literals;
246 static constexpr auto kServiceRetryPeriod = 5s;
247 LOG(INFO) << "Failed to retrieve component traits from service "
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700248 "\"" << GetServiceNames()[mIndex] << "\". "
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700249 "Retrying...";
250 std::this_thread::sleep_for(kServiceRetryPeriod);
251 }
252 });
253 return mTraits;
254 }
255
256 // List() returns the list of all caches.
257 static std::vector<Cache>& List() {
258 static std::vector<Cache> sCaches{[]() {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700259 size_t numServices = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700260 std::vector<Cache> caches(numServices);
261 for (size_t i = 0; i < numServices; ++i) {
262 caches[i].init(i);
263 }
264 return caches;
265 }()};
266 return sCaches;
267 }
268};
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800269// Codec2ConfigurableClient::HidlImpl
Pawin Vongmasa36653902018-11-15 00:10:25 -0800270
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800271struct Codec2ConfigurableClient::HidlImpl : public Codec2ConfigurableClient::ImplBase {
272 typedef c2_hidl::IConfigurable Base;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800273
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800274 // base cannot be null.
275 explicit HidlImpl(const sp<Base>& base);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800276
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800277 const C2String& getName() const override {
278 return mName;
279 }
280
281 c2_status_t query(
282 const std::vector<C2Param*>& stackParams,
283 const std::vector<C2Param::Index> &heapParamIndices,
284 c2_blocking_t mayBlock,
285 std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
286
287 c2_status_t config(
288 const std::vector<C2Param*> &params,
289 c2_blocking_t mayBlock,
290 std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
291
292 c2_status_t querySupportedParams(
293 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
294 ) const override;
295
296 c2_status_t querySupportedValues(
297 std::vector<C2FieldSupportedValuesQuery>& fields,
298 c2_blocking_t mayBlock) const override;
299
300private:
301 sp<Base> mBase;
302 const C2String mName;
303};
304
305Codec2ConfigurableClient::HidlImpl::HidlImpl(const sp<Base>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800306 : mBase{base},
307 mName{[base]() -> C2String {
308 C2String outName;
309 Return<void> transStatus = base->getName(
310 [&outName](const hidl_string& name) {
311 outName = name.c_str();
312 });
313 return transStatus.isOk() ? outName : "";
314 }()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800315}
316
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800317c2_status_t Codec2ConfigurableClient::HidlImpl::query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800318 const std::vector<C2Param*> &stackParams,
319 const std::vector<C2Param::Index> &heapParamIndices,
320 c2_blocking_t mayBlock,
321 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800322 hidl_vec<c2_hidl::ParamIndex> indices(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800323 stackParams.size() + heapParamIndices.size());
324 size_t numIndices = 0;
325 for (C2Param* const& stackParam : stackParams) {
326 if (!stackParam) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800327 LOG(WARNING) << "query -- null stack param encountered.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800328 continue;
329 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800330 indices[numIndices++] = static_cast<c2_hidl::ParamIndex>(stackParam->index());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800331 }
332 size_t numStackIndices = numIndices;
333 for (const C2Param::Index& index : heapParamIndices) {
334 indices[numIndices++] =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800335 static_cast<c2_hidl::ParamIndex>(static_cast<uint32_t>(index));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800336 }
337 indices.resize(numIndices);
338 if (heapParams) {
339 heapParams->reserve(heapParams->size() + numIndices);
340 }
341 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800342 Return<void> transStatus = mBase->query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800343 indices,
344 mayBlock == C2_MAY_BLOCK,
345 [&status, &numStackIndices, &stackParams, heapParams](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800346 c2_hidl::Status s, const c2_hidl::Params& p) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800347 status = static_cast<c2_status_t>(s);
348 if (status != C2_OK && status != C2_BAD_INDEX) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800349 LOG(DEBUG) << "query -- call failed: "
350 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800351 return;
352 }
353 std::vector<C2Param*> paramPointers;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800354 if (!c2_hidl::utils::parseParamsBlob(&paramPointers, p)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800355 LOG(ERROR) << "query -- error while parsing params.";
356 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800357 return;
358 }
359 size_t i = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800360 for (auto it = paramPointers.begin();
361 it != paramPointers.end(); ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800362 C2Param* paramPointer = *it;
363 if (numStackIndices > 0) {
364 --numStackIndices;
365 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800366 LOG(WARNING) << "query -- null stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800367 ++it;
368 continue;
369 }
370 for (; i < stackParams.size() && !stackParams[i]; ) {
371 ++i;
372 }
373 if (i >= stackParams.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800374 LOG(ERROR) << "query -- unexpected error.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800375 status = C2_CORRUPTED;
376 return;
377 }
378 if (stackParams[i]->index() != paramPointer->index()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800379 LOG(WARNING) << "query -- param skipped: "
380 "index = "
381 << stackParams[i]->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800382 stackParams[i++]->invalidate();
383 continue;
384 }
385 if (!stackParams[i++]->updateFrom(*paramPointer)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800386 LOG(WARNING) << "query -- param update failed: "
387 "index = "
388 << paramPointer->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800389 }
390 } else {
391 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800392 LOG(WARNING) << "query -- null heap param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800393 ++it;
394 continue;
395 }
396 if (!heapParams) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800397 LOG(WARNING) << "query -- "
398 "unexpected extra stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800399 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800400 heapParams->emplace_back(
401 C2Param::Copy(*paramPointer));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800402 }
403 }
404 ++it;
405 }
406 });
407 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800408 LOG(ERROR) << "query -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800409 return C2_TRANSACTION_FAILED;
410 }
411 return status;
412}
413
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800414c2_status_t Codec2ConfigurableClient::HidlImpl::config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800415 const std::vector<C2Param*> &params,
416 c2_blocking_t mayBlock,
417 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800418 c2_hidl::Params hidlParams;
419 if (!c2_hidl::utils::createParamsBlob(&hidlParams, params)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800420 LOG(ERROR) << "config -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800421 return C2_TRANSACTION_FAILED;
422 }
423 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800424 Return<void> transStatus = mBase->config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800425 hidlParams,
426 mayBlock == C2_MAY_BLOCK,
427 [&status, &params, failures](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800428 c2_hidl::Status s,
429 const hidl_vec<c2_hidl::SettingResult> f,
430 const c2_hidl::Params& o) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800431 status = static_cast<c2_status_t>(s);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800432 if (status != C2_OK && status != C2_BAD_INDEX) {
433 LOG(DEBUG) << "config -- call failed: "
434 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800435 }
436 size_t i = failures->size();
437 failures->resize(i + f.size());
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800438 for (const c2_hidl::SettingResult& sf : f) {
439 if (!c2_hidl::utils::objcpy(&(*failures)[i++], sf)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800440 LOG(ERROR) << "config -- "
441 << "invalid SettingResult returned.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800442 return;
443 }
444 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800445 if (!c2_hidl::utils::updateParamsFromBlob(params, o)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800446 LOG(ERROR) << "config -- "
447 << "failed to parse returned params.";
448 status = C2_CORRUPTED;
449 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800450 });
451 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800452 LOG(ERROR) << "config -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800453 return C2_TRANSACTION_FAILED;
454 }
455 return status;
456}
457
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800458c2_status_t Codec2ConfigurableClient::HidlImpl::querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800459 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
460 // TODO: Cache and query properly!
461 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800462 Return<void> transStatus = mBase->querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800463 std::numeric_limits<uint32_t>::min(),
464 std::numeric_limits<uint32_t>::max(),
465 [&status, params](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800466 c2_hidl::Status s,
467 const hidl_vec<c2_hidl::ParamDescriptor>& p) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800468 status = static_cast<c2_status_t>(s);
469 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800470 LOG(DEBUG) << "querySupportedParams -- call failed: "
471 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800472 return;
473 }
474 size_t i = params->size();
475 params->resize(i + p.size());
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800476 for (const c2_hidl::ParamDescriptor& sp : p) {
477 if (!c2_hidl::utils::objcpy(&(*params)[i++], sp)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800478 LOG(ERROR) << "querySupportedParams -- "
479 << "invalid returned ParamDescriptor.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800480 return;
481 }
482 }
483 });
484 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800485 LOG(ERROR) << "querySupportedParams -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800486 return C2_TRANSACTION_FAILED;
487 }
488 return status;
489}
490
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800491c2_status_t Codec2ConfigurableClient::HidlImpl::querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800492 std::vector<C2FieldSupportedValuesQuery>& fields,
493 c2_blocking_t mayBlock) const {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800494 hidl_vec<c2_hidl::FieldSupportedValuesQuery> inFields(fields.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800495 for (size_t i = 0; i < fields.size(); ++i) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800496 if (!c2_hidl::utils::objcpy(&inFields[i], fields[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800497 LOG(ERROR) << "querySupportedValues -- bad input";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800498 return C2_TRANSACTION_FAILED;
499 }
500 }
501
502 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800503 Return<void> transStatus = mBase->querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800504 inFields,
505 mayBlock == C2_MAY_BLOCK,
506 [&status, &inFields, &fields](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800507 c2_hidl::Status s,
508 const hidl_vec<c2_hidl::FieldSupportedValuesQueryResult>& r) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800509 status = static_cast<c2_status_t>(s);
510 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800511 LOG(DEBUG) << "querySupportedValues -- call failed: "
512 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800513 return;
514 }
515 if (r.size() != fields.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800516 LOG(ERROR) << "querySupportedValues -- "
517 "input and output lists "
518 "have different sizes.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800519 status = C2_CORRUPTED;
520 return;
521 }
522 for (size_t i = 0; i < fields.size(); ++i) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800523 if (!c2_hidl::utils::objcpy(&fields[i], inFields[i], r[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800524 LOG(ERROR) << "querySupportedValues -- "
525 "invalid returned value.";
526 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800527 return;
528 }
529 }
530 });
531 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800532 LOG(ERROR) << "querySupportedValues -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800533 return C2_TRANSACTION_FAILED;
534 }
535 return status;
536}
537
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800538// Codec2ConfigurableClient::AidlImpl
539
540struct Codec2ConfigurableClient::AidlImpl : public Codec2ConfigurableClient::ImplBase {
541 typedef c2_aidl::IConfigurable Base;
542
543 // base cannot be null.
544 explicit AidlImpl(const std::shared_ptr<Base>& base);
545
546 const C2String& getName() const override {
547 return mName;
548 }
549
550 c2_status_t query(
551 const std::vector<C2Param*>& stackParams,
552 const std::vector<C2Param::Index> &heapParamIndices,
553 c2_blocking_t mayBlock,
554 std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
555
556 c2_status_t config(
557 const std::vector<C2Param*> &params,
558 c2_blocking_t mayBlock,
559 std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
560
561 c2_status_t querySupportedParams(
562 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
563 ) const override;
564
565 c2_status_t querySupportedValues(
566 std::vector<C2FieldSupportedValuesQuery>& fields,
567 c2_blocking_t mayBlock) const override;
568
569private:
570 std::shared_ptr<Base> mBase;
571 const C2String mName;
572};
573
574Codec2ConfigurableClient::AidlImpl::AidlImpl(const std::shared_ptr<Base>& base)
575 : mBase{base},
576 mName{[base]() -> C2String {
577 std::string outName;
578 ndk::ScopedAStatus status = base->getName(&outName);
579 return status.isOk() ? outName : "";
580 }()} {
581}
582
583c2_status_t Codec2ConfigurableClient::AidlImpl::query(
584 const std::vector<C2Param*> &stackParams,
585 const std::vector<C2Param::Index> &heapParamIndices,
586 c2_blocking_t mayBlock,
587 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
Wonsik Kim1caded02022-12-09 13:03:11 -0800588 std::vector<int> indices(
589 stackParams.size() + heapParamIndices.size());
590 size_t numIndices = 0;
591 for (C2Param* const& stackParam : stackParams) {
592 if (!stackParam) {
593 LOG(WARNING) << "query -- null stack param encountered.";
594 continue;
595 }
596 indices[numIndices++] = int(stackParam->index());
597 }
598 size_t numStackIndices = numIndices;
599 for (const C2Param::Index& index : heapParamIndices) {
600 indices[numIndices++] = int(static_cast<uint32_t>(index));
601 }
602 indices.resize(numIndices);
603 if (heapParams) {
604 heapParams->reserve(heapParams->size() + numIndices);
605 }
606 c2_aidl::Params result;
607 ndk::ScopedAStatus transStatus = mBase->query(indices, (mayBlock == C2_MAY_BLOCK), &result);
608 if (!transStatus.isOk()) {
609 if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
610 c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
611 LOG(DEBUG) << "query -- call failed: " << status << ".";
612 return status;
613 } else {
614 LOG(ERROR) << "query -- transaction failed.";
615 return C2_TRANSACTION_FAILED;
616 }
617 }
618
619 c2_status_t status = C2_OK;
620 std::vector<C2Param*> paramPointers;
621 if (!c2_aidl::utils::ParseParamsBlob(&paramPointers, result)) {
622 LOG(ERROR) << "query -- error while parsing params.";
623 return C2_CORRUPTED;
624 }
625 size_t i = 0;
626 for (auto it = paramPointers.begin();
627 it != paramPointers.end(); ) {
628 C2Param* paramPointer = *it;
629 if (numStackIndices > 0) {
630 --numStackIndices;
631 if (!paramPointer) {
632 LOG(DEBUG) << "query -- null stack param.";
633 ++it;
634 continue;
635 }
636 for (; i < stackParams.size() && !stackParams[i]; ) {
637 ++i;
638 }
639 if (i >= stackParams.size()) {
640 LOG(ERROR) << "query -- unexpected error.";
641 status = C2_CORRUPTED;
642 break;
643 }
644 if (stackParams[i]->index() != paramPointer->index()) {
645 LOG(DEBUG) << "query -- param skipped: "
646 "index = "
647 << stackParams[i]->index() << ".";
648 stackParams[i++]->invalidate();
649 // this means that the param could not be queried.
650 // signalling C2_BAD_INDEX to the client.
651 status = C2_BAD_INDEX;
652 continue;
653 }
654 if (!stackParams[i++]->updateFrom(*paramPointer)) {
655 LOG(WARNING) << "query -- param update failed: "
656 "index = "
657 << paramPointer->index() << ".";
658 }
659 } else {
660 if (!paramPointer) {
661 LOG(DEBUG) << "query -- null heap param.";
662 ++it;
663 continue;
664 }
665 if (!heapParams) {
666 LOG(WARNING) << "query -- "
667 "unexpected extra stack param.";
668 } else {
669 heapParams->emplace_back(C2Param::Copy(*paramPointer));
670 }
671 }
672 ++it;
673 }
674 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800675}
676
677c2_status_t Codec2ConfigurableClient::AidlImpl::config(
678 const std::vector<C2Param*> &params,
679 c2_blocking_t mayBlock,
680 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
Wonsik Kim1caded02022-12-09 13:03:11 -0800681 c2_aidl::Params aidlParams;
682 if (!c2_aidl::utils::CreateParamsBlob(&aidlParams, params)) {
683 LOG(ERROR) << "config -- bad input.";
684 return C2_TRANSACTION_FAILED;
685 }
686 c2_aidl::IConfigurable::ConfigResult result;
687 ndk::ScopedAStatus transStatus = mBase->config(aidlParams, (mayBlock == C2_MAY_BLOCK), &result);
688 if (!transStatus.isOk()) {
689 if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
690 c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
691 LOG(DEBUG) << "config -- call failed: " << status << ".";
692 return status;
693 } else {
694 LOG(ERROR) << "config -- transaction failed.";
695 return C2_TRANSACTION_FAILED;
696 }
697 }
698 c2_status_t status = C2_OK;
699 size_t i = failures->size();
700 failures->resize(i + result.failures.size());
701 for (const c2_aidl::SettingResult& sf : result.failures) {
702 if (!c2_aidl::utils::FromAidl(&(*failures)[i++], sf)) {
703 LOG(ERROR) << "config -- invalid SettingResult returned.";
704 return C2_CORRUPTED;
705 }
706 }
707 if (!c2_aidl::utils::UpdateParamsFromBlob(params, result.params)) {
708 LOG(ERROR) << "config -- "
709 << "failed to parse returned params.";
710 status = C2_CORRUPTED;
711 }
712 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800713}
714
715c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedParams(
716 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
Wonsik Kim1caded02022-12-09 13:03:11 -0800717 // TODO: Cache and query properly!
718 std::vector<c2_aidl::ParamDescriptor> result;
719 ndk::ScopedAStatus transStatus = mBase->querySupportedParams(
720 std::numeric_limits<uint32_t>::min(),
721 std::numeric_limits<uint32_t>::max(),
722 &result);
723 if (!transStatus.isOk()) {
724 if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
725 c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
726 LOG(DEBUG) << "querySupportedParams -- call failed: " << status << ".";
727 return status;
728 } else {
729 LOG(ERROR) << "querySupportedParams -- transaction failed.";
730 return C2_TRANSACTION_FAILED;
731 }
732 }
733 c2_status_t status = C2_OK;
734 size_t i = params->size();
735 params->resize(i + result.size());
736 for (const c2_aidl::ParamDescriptor& sp : result) {
737 if (!c2_aidl::utils::FromAidl(&(*params)[i++], sp)) {
738 LOG(ERROR) << "querySupportedParams -- invalid returned ParamDescriptor.";
739 return C2_CORRUPTED;
740 }
741 }
742 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800743}
744
745c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedValues(
746 std::vector<C2FieldSupportedValuesQuery>& fields,
747 c2_blocking_t mayBlock) const {
Wonsik Kim1caded02022-12-09 13:03:11 -0800748 std::vector<c2_aidl::FieldSupportedValuesQuery> inFields(fields.size());
749 for (size_t i = 0; i < fields.size(); ++i) {
750 if (!c2_aidl::utils::ToAidl(&inFields[i], fields[i])) {
751 LOG(ERROR) << "querySupportedValues -- bad input";
752 return C2_TRANSACTION_FAILED;
753 }
754 }
755
756 std::vector<c2_aidl::FieldSupportedValuesQueryResult> result;
757 ndk::ScopedAStatus transStatus = mBase->querySupportedValues(
758 inFields, (mayBlock == C2_MAY_BLOCK), &result);
759 if (!transStatus.isOk()) {
760 if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
761 c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
762 LOG(DEBUG) << "querySupportedValues -- call failed: " << status << ".";
763 return status;
764 } else {
765 LOG(ERROR) << "querySupportedValues -- transaction failed.";
766 return C2_TRANSACTION_FAILED;
767 }
768 }
769 c2_status_t status = C2_OK;
770 if (result.size() != fields.size()) {
771 LOG(ERROR) << "querySupportedValues -- "
772 "input and output lists "
773 "have different sizes.";
774 return C2_CORRUPTED;
775 }
776 for (size_t i = 0; i < fields.size(); ++i) {
777 if (!c2_aidl::utils::FromAidl(&fields[i], inFields[i], result[i])) {
778 LOG(ERROR) << "querySupportedValues -- "
779 "invalid returned value.";
780 return C2_CORRUPTED;
781 }
782 }
783 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800784}
785
786// Codec2ConfigurableClient
787
788Codec2ConfigurableClient::Codec2ConfigurableClient(const sp<HidlBase> &hidlBase)
789 : mImpl(new Codec2ConfigurableClient::HidlImpl(hidlBase)) {
790}
791
792Codec2ConfigurableClient::Codec2ConfigurableClient(
793 const std::shared_ptr<AidlBase> &aidlBase)
794 : mImpl(new Codec2ConfigurableClient::AidlImpl(aidlBase)) {
795}
796
797const C2String& Codec2ConfigurableClient::getName() const {
798 return mImpl->getName();
799}
800
801c2_status_t Codec2ConfigurableClient::query(
802 const std::vector<C2Param*>& stackParams,
803 const std::vector<C2Param::Index> &heapParamIndices,
804 c2_blocking_t mayBlock,
805 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
806 return mImpl->query(stackParams, heapParamIndices, mayBlock, heapParams);
807}
808
809c2_status_t Codec2ConfigurableClient::config(
810 const std::vector<C2Param*> &params,
811 c2_blocking_t mayBlock,
812 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
813 return mImpl->config(params, mayBlock, failures);
814}
815
816c2_status_t Codec2ConfigurableClient::querySupportedParams(
817 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
818 return mImpl->querySupportedParams(params);
819}
820
821c2_status_t Codec2ConfigurableClient::querySupportedValues(
822 std::vector<C2FieldSupportedValuesQuery>& fields,
823 c2_blocking_t mayBlock) const {
824 return mImpl->querySupportedValues(fields, mayBlock);
825}
826
827
Pawin Vongmasa36653902018-11-15 00:10:25 -0800828// Codec2Client::Component::HidlListener
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800829struct Codec2Client::Component::HidlListener : public c2_hidl::IComponentListener {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800830 std::weak_ptr<Component> component;
831 std::weak_ptr<Listener> base;
832
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800833 virtual Return<void> onWorkDone(const c2_hidl::WorkBundle& workBundle) override {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800834 std::list<std::unique_ptr<C2Work>> workItems;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800835 if (!c2_hidl::utils::objcpy(&workItems, workBundle)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800836 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800837 return Void();
838 }
839 // release input buffers potentially held by the component from queue
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800840 std::shared_ptr<Codec2Client::Component> strongComponent =
841 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800842 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800843 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800844 }
845 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800846 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800847 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800848 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800849 }
850 return Void();
851 }
852
853 virtual Return<void> onTripped(
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800854 const hidl_vec<c2_hidl::SettingResult>& settingResults) override {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800855 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
856 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800857 for (size_t i = 0; i < settingResults.size(); ++i) {
858 std::unique_ptr<C2SettingResult> c2SettingResult;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800859 if (!c2_hidl::utils::objcpy(&c2SettingResult, settingResults[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800860 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800861 return Void();
862 }
863 c2SettingResults[i] = std::move(c2SettingResult);
864 }
865 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
866 listener->onTripped(component, c2SettingResults);
867 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800868 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800869 }
870 return Void();
871 }
872
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800873 virtual Return<void> onError(c2_hidl::Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800874 LOG(DEBUG) << "onError --"
875 << " status = " << s
876 << ", errorCode = " << errorCode
877 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800878 if (std::shared_ptr<Listener> listener = base.lock()) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800879 listener->onError(component, s == c2_hidl::Status::OK ?
Pawin Vongmasa36653902018-11-15 00:10:25 -0800880 errorCode : static_cast<c2_status_t>(s));
881 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800882 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800883 }
884 return Void();
885 }
886
887 virtual Return<void> onFramesRendered(
888 const hidl_vec<RenderedFrame>& renderedFrames) override {
889 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800890 if (!listener) {
891 LOG(DEBUG) << "onFramesRendered -- listener died.";
892 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800893 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800894 for (const RenderedFrame& renderedFrame : renderedFrames) {
895 listener->onFrameRendered(
896 renderedFrame.bufferQueueId,
897 renderedFrame.slotId,
898 renderedFrame.timestampNs);
899 }
900 return Void();
901 }
902
903 virtual Return<void> onInputBuffersReleased(
904 const hidl_vec<InputBuffer>& inputBuffers) override {
905 std::shared_ptr<Listener> listener = base.lock();
906 if (!listener) {
907 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
908 return Void();
909 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800910 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800911 LOG(VERBOSE) << "onInputBuffersReleased --"
912 " received death notification of"
913 " input buffer:"
914 " frameIndex = " << inputBuffer.frameIndex
915 << ", bufferIndex = " << inputBuffer.arrayIndex
916 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -0800917 listener->onInputBufferDone(
918 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800919 }
920 return Void();
921 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800922
Pawin Vongmasa36653902018-11-15 00:10:25 -0800923};
924
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700925// Codec2Client::Component::BufferPoolSender
926struct Codec2Client::Component::BufferPoolSender :
927 hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
928 BufferPoolSender()
929 : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
930 }
931};
932
933// Codec2Client::Component::OutputBufferQueue
934struct Codec2Client::Component::OutputBufferQueue :
Sungtak Leea714f112021-03-16 05:40:03 -0700935 hardware::media::c2::OutputBufferQueue {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700936 OutputBufferQueue()
Sungtak Leea714f112021-03-16 05:40:03 -0700937 : hardware::media::c2::OutputBufferQueue() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700938 }
939};
940
Pawin Vongmasa36653902018-11-15 00:10:25 -0800941// Codec2Client
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700942Codec2Client::Codec2Client(sp<Base> const& base,
Sungtak Leef4b39512023-05-10 07:17:22 +0000943 sp<c2_hidl::IConfigurable> const& configurable,
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700944 size_t serviceIndex)
Sungtak Leef4b39512023-05-10 07:17:22 +0000945 : Configurable{configurable},
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700946 mBase1_0{base},
947 mBase1_1{Base1_1::castFrom(base)},
Sungtak Lee8577dab2021-03-12 02:25:50 -0800948 mBase1_2{Base1_2::castFrom(base)},
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700949 mServiceIndex{serviceIndex} {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800950 Return<sp<bufferpool_hidl::IClientManager>> transResult = base->getPoolClientManager();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800951 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800952 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800953 } else {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800954 mHostPoolManager = static_cast<sp<bufferpool_hidl::IClientManager>>(transResult);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800955 }
956}
957
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700958sp<Codec2Client::Base> const& Codec2Client::getBase() const {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700959 return mBase1_0;
960}
961
962sp<Codec2Client::Base1_0> const& Codec2Client::getBase1_0() const {
963 return mBase1_0;
964}
965
966sp<Codec2Client::Base1_1> const& Codec2Client::getBase1_1() const {
967 return mBase1_1;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700968}
969
Sungtak Lee8577dab2021-03-12 02:25:50 -0800970sp<Codec2Client::Base1_2> const& Codec2Client::getBase1_2() const {
971 return mBase1_2;
972}
973
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700974std::string const& Codec2Client::getServiceName() const {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700975 return GetServiceNames()[mServiceIndex];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700976}
977
Pawin Vongmasa36653902018-11-15 00:10:25 -0800978c2_status_t Codec2Client::createComponent(
979 const C2String& name,
980 const std::shared_ptr<Codec2Client::Listener>& listener,
981 std::shared_ptr<Codec2Client::Component>* const component) {
982
Pawin Vongmasa36653902018-11-15 00:10:25 -0800983 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800984 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800985 hidlListener->base = listener;
Sungtak Lee8577dab2021-03-12 02:25:50 -0800986 Return<void> transStatus;
987 if (mBase1_2) {
988 transStatus = mBase1_2->createComponent_1_2(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800989 name,
990 hidlListener,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800991 bufferpool_hidl::implementation::ClientManager::getInstance(),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800992 [&status, component, hidlListener](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800993 c2_hidl::Status s,
994 const sp<c2_hidl::IComponent>& c) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800995 status = static_cast<c2_status_t>(s);
996 if (status != C2_OK) {
997 return;
998 }
999 *component = std::make_shared<Codec2Client::Component>(c);
1000 hidlListener->component = *component;
Sungtak Lee8577dab2021-03-12 02:25:50 -08001001 });
1002 }
1003 else if (mBase1_1) {
1004 transStatus = mBase1_1->createComponent_1_1(
1005 name,
1006 hidlListener,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001007 bufferpool_hidl::implementation::ClientManager::getInstance(),
Sungtak Lee8577dab2021-03-12 02:25:50 -08001008 [&status, component, hidlListener](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001009 c2_hidl::Status s,
1010 const sp<c2_hidl_base::V1_1::IComponent>& c) {
Sungtak Lee8577dab2021-03-12 02:25:50 -08001011 status = static_cast<c2_status_t>(s);
1012 if (status != C2_OK) {
1013 return;
1014 }
1015 *component = std::make_shared<Codec2Client::Component>(c);
1016 hidlListener->component = *component;
1017 });
1018 } else if (mBase1_0) { // ver1_0
1019 transStatus = mBase1_0->createComponent(
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001020 name,
1021 hidlListener,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001022 bufferpool_hidl::implementation::ClientManager::getInstance(),
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001023 [&status, component, hidlListener](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001024 c2_hidl::Status s,
1025 const sp<c2_hidl_base::V1_0::IComponent>& c) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001026 status = static_cast<c2_status_t>(s);
1027 if (status != C2_OK) {
1028 return;
1029 }
1030 *component = std::make_shared<Codec2Client::Component>(c);
1031 hidlListener->component = *component;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001032 });
Sungtak Lee8577dab2021-03-12 02:25:50 -08001033 } else {
1034 status = C2_CORRUPTED;
1035 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001036 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001037 LOG(ERROR) << "createComponent(" << name.c_str()
1038 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001039 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001040 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08001041 if (status == C2_NOT_FOUND) {
1042 LOG(VERBOSE) << "createComponent(" << name.c_str()
1043 << ") -- component not found.";
1044 } else {
1045 LOG(ERROR) << "createComponent(" << name.c_str()
1046 << ") -- call failed: " << status << ".";
1047 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001048 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001049 } else if (!*component) {
1050 LOG(ERROR) << "createComponent(" << name.c_str()
1051 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001052 return C2_CORRUPTED;
1053 }
1054
1055 status = (*component)->setDeathListener(*component, listener);
1056 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001057 LOG(ERROR) << "createComponent(" << name.c_str()
1058 << ") -- failed to set up death listener: "
1059 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001060 }
1061
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001062 (*component)->mBufferPoolSender->setReceiver(mHostPoolManager);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001063 return status;
1064}
1065
1066c2_status_t Codec2Client::createInterface(
1067 const C2String& name,
1068 std::shared_ptr<Codec2Client::Interface>* const interface) {
1069 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001070 Return<void> transStatus = mBase1_0->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001071 name,
1072 [&status, interface](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001073 c2_hidl::Status s,
1074 const sp<c2_hidl::IComponentInterface>& i) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001075 status = static_cast<c2_status_t>(s);
1076 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001077 return;
1078 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001079 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001080 });
1081 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001082 LOG(ERROR) << "createInterface(" << name.c_str()
1083 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001084 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001085 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08001086 if (status == C2_NOT_FOUND) {
1087 LOG(VERBOSE) << "createInterface(" << name.c_str()
1088 << ") -- component not found.";
1089 } else {
1090 LOG(ERROR) << "createInterface(" << name.c_str()
1091 << ") -- call failed: " << status << ".";
1092 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001093 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001094 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001095
Pawin Vongmasa36653902018-11-15 00:10:25 -08001096 return status;
1097}
1098
1099c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001100 std::shared_ptr<InputSurface>* const inputSurface) {
1101 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001102 Return<void> transStatus = mBase1_0->createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001103 [&status, inputSurface](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001104 c2_hidl::Status s,
1105 const sp<c2_hidl::IInputSurface>& i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001106 status = static_cast<c2_status_t>(s);
1107 if (status != C2_OK) {
1108 return;
1109 }
1110 *inputSurface = std::make_shared<InputSurface>(i);
1111 });
1112 if (!transStatus.isOk()) {
1113 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001114 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001115 } else if (status != C2_OK) {
1116 LOG(DEBUG) << "createInputSurface -- call failed: "
1117 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001118 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001119 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001120}
1121
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001122std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
1123 return Cache::List()[mServiceIndex].getTraits();
1124}
1125
1126std::vector<C2Component::Traits> Codec2Client::_listComponents(
1127 bool* success) const {
1128 std::vector<C2Component::Traits> traits;
1129 std::string const& serviceName = getServiceName();
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001130 Return<void> transStatus = mBase1_0->listComponents(
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001131 [&traits, &serviceName](c2_hidl::Status s,
1132 const hidl_vec<c2_hidl::IComponentStore::ComponentTraits>& t) {
1133 if (s != c2_hidl::Status::OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001134 LOG(DEBUG) << "_listComponents -- call failed: "
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001135 << static_cast<c2_status_t>(s) << ".";
1136 return;
1137 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001138 traits.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001139 for (size_t i = 0; i < t.size(); ++i) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001140 if (!c2_hidl::utils::objcpy(&traits[i], t[i])) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001141 LOG(ERROR) << "_listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001142 return;
1143 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001144 traits[i].owner = serviceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001145 }
1146 });
1147 if (!transStatus.isOk()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001148 LOG(ERROR) << "_listComponents -- transaction failed.";
1149 *success = false;
1150 } else {
1151 *success = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001152 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001153 return traits;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001154}
1155
1156c2_status_t Codec2Client::copyBuffer(
1157 const std::shared_ptr<C2Buffer>& src,
1158 const std::shared_ptr<C2Buffer>& dst) {
1159 // TODO: Implement?
1160 (void)src;
1161 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001162 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001163 return C2_OMITTED;
1164}
1165
1166std::shared_ptr<C2ParamReflector>
1167 Codec2Client::getParamReflector() {
1168 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
1169 // should reflect the HAL API.
1170 struct SimpleParamReflector : public C2ParamReflector {
1171 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001172 hidl_vec<c2_hidl::ParamIndex> indices(1);
1173 indices[0] = static_cast<c2_hidl::ParamIndex>(coreIndex.coreIndex());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001174 std::unique_ptr<C2StructDescriptor> descriptor;
1175 Return<void> transStatus = mBase->getStructDescriptors(
1176 indices,
1177 [&descriptor](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001178 c2_hidl::Status s,
1179 const hidl_vec<c2_hidl::StructDescriptor>& sd) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001180 c2_status_t status = static_cast<c2_status_t>(s);
1181 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001182 LOG(DEBUG) << "SimpleParamReflector -- "
1183 "getStructDescriptors() failed: "
1184 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001185 descriptor.reset();
1186 return;
1187 }
1188 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001189 LOG(DEBUG) << "SimpleParamReflector -- "
1190 "getStructDescriptors() "
1191 "returned vector of size "
1192 << sd.size() << ". "
1193 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001194 descriptor.reset();
1195 return;
1196 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001197 if (!c2_hidl::utils::objcpy(&descriptor, sd[0])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001198 LOG(DEBUG) << "SimpleParamReflector -- "
1199 "getStructDescriptors() returned "
1200 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001201 descriptor.reset();
1202 return;
1203 }
1204 });
Wonsik Kim492fecd2020-11-19 11:14:11 -08001205 if (!transStatus.isOk()) {
1206 LOG(DEBUG) << "SimpleParamReflector -- transaction failed: "
1207 << transStatus.description();
1208 descriptor.reset();
1209 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001210 return descriptor;
1211 }
1212
1213 SimpleParamReflector(sp<Base> base)
1214 : mBase(base) { }
1215
1216 sp<Base> mBase;
1217 };
1218
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001219 return std::make_shared<SimpleParamReflector>(mBase1_0);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001220};
1221
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001222std::vector<std::string> const& Codec2Client::GetServiceNames() {
1223 static std::vector<std::string> sServiceNames{[]() {
1224 using ::android::hardware::media::c2::V1_0::IComponentStore;
1225 using ::android::hidl::manager::V1_2::IServiceManager;
1226
1227 while (true) {
1228 sp<IServiceManager> serviceManager = IServiceManager::getService();
1229 CHECK(serviceManager) << "Hardware service manager is not running.";
1230
1231 // There are three categories of services based on names.
1232 std::vector<std::string> defaultNames; // Prefixed with "default"
1233 std::vector<std::string> vendorNames; // Prefixed with "vendor"
1234 std::vector<std::string> otherNames; // Others
1235 Return<void> transResult;
1236 transResult = serviceManager->listManifestByInterface(
1237 IComponentStore::descriptor,
1238 [&defaultNames, &vendorNames, &otherNames](
1239 hidl_vec<hidl_string> const& instanceNames) {
1240 for (hidl_string const& instanceName : instanceNames) {
1241 char const* name = instanceName.c_str();
1242 if (strncmp(name, "default", 7) == 0) {
1243 defaultNames.emplace_back(name);
1244 } else if (strncmp(name, "vendor", 6) == 0) {
1245 vendorNames.emplace_back(name);
1246 } else {
1247 otherNames.emplace_back(name);
1248 }
1249 }
1250 });
1251 if (transResult.isOk()) {
1252 // Sort service names in each category.
1253 std::sort(defaultNames.begin(), defaultNames.end());
1254 std::sort(vendorNames.begin(), vendorNames.end());
1255 std::sort(otherNames.begin(), otherNames.end());
1256
1257 // Concatenate the three lists in this order: default, vendor,
1258 // other.
1259 std::vector<std::string>& names = defaultNames;
1260 names.reserve(names.size() + vendorNames.size() + otherNames.size());
1261 names.insert(names.end(),
1262 std::make_move_iterator(vendorNames.begin()),
1263 std::make_move_iterator(vendorNames.end()));
1264 names.insert(names.end(),
1265 std::make_move_iterator(otherNames.begin()),
1266 std::make_move_iterator(otherNames.end()));
1267
1268 // Summarize to logcat.
1269 if (names.empty()) {
1270 LOG(INFO) << "No Codec2 services declared in the manifest.";
1271 } else {
1272 std::stringstream stringOutput;
1273 stringOutput << "Available Codec2 services:";
1274 for (std::string const& name : names) {
1275 stringOutput << " \"" << name << "\"";
1276 }
1277 LOG(INFO) << stringOutput.str();
1278 }
1279
1280 return names;
1281 }
1282 LOG(ERROR) << "Could not retrieve the list of service instances of "
1283 << IComponentStore::descriptor
1284 << ". Retrying...";
1285 }
1286 }()};
1287 return sServiceNames;
1288}
1289
Pawin Vongmasa36653902018-11-15 00:10:25 -08001290std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa83d2c552020-03-05 04:36:08 -08001291 const char* name,
1292 bool setAsPreferredCodec2ComponentStore) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001293 size_t index = getServiceIndex(name);
Pawin Vongmasa83d2c552020-03-05 04:36:08 -08001294 if (index == GetServiceNames().size()) {
1295 if (setAsPreferredCodec2ComponentStore) {
1296 LOG(WARNING) << "CreateFromService(" << name
1297 << ") -- preferred C2ComponentStore not set.";
1298 }
1299 return nullptr;
1300 }
1301 std::shared_ptr<Codec2Client> client = _CreateFromIndex(index);
1302 if (setAsPreferredCodec2ComponentStore) {
1303 SetPreferredCodec2ComponentStore(
1304 std::make_shared<Client2Store>(client));
1305 LOG(INFO) << "CreateFromService(" << name
1306 << ") -- service set as preferred C2ComponentStore.";
1307 }
1308 return client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001309}
1310
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001311std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
1312 CreateFromAllServices() {
1313 std::vector<std::shared_ptr<Codec2Client>> clients(
1314 GetServiceNames().size());
1315 for (size_t i = GetServiceNames().size(); i > 0; ) {
1316 --i;
1317 clients[i] = _CreateFromIndex(i);
1318 }
1319 return clients;
1320}
1321
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001322std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001323 std::string const& name = GetServiceNames()[index];
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08001324 LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001325 sp<Base> baseStore = Base::getService(name);
1326 CHECK(baseStore) << "Codec2 service \"" << name << "\""
1327 " inaccessible for unknown reasons.";
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08001328 LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
Sungtak Leef4b39512023-05-10 07:17:22 +00001329 Return<sp<IConfigurable>> transResult = baseStore->getConfigurable();
1330 CHECK(transResult.isOk()) << "Codec2 service \"" << name << "\""
1331 "does not have IConfigurable.";
1332 sp<IConfigurable> configurable = static_cast<sp<IConfigurable>>(transResult);
1333 return std::make_shared<Codec2Client>(baseStore, configurable, index);
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001334}
1335
1336c2_status_t Codec2Client::ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001337 const std::string &key,
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001338 size_t numberOfAttempts,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001339 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
1340 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001341 c2_status_t status = C2_NO_INIT; // no IComponentStores present
1342
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001343 // Cache the mapping key -> index of Codec2Client in Cache::List().
Pawin Vongmasa36653902018-11-15 00:10:25 -08001344 static std::mutex key2IndexMutex;
1345 static std::map<std::string, size_t> key2Index;
1346
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001347 // By default try all stores. However, try the last known client first. If
1348 // the last known client fails, retry once. We do this by pushing the last
1349 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -08001350 std::deque<size_t> indices;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001351 for (size_t index = Cache::List().size(); index > 0; ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001352 indices.push_front(--index);
1353 }
1354
1355 bool wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001356 {
1357 std::scoped_lock lock{key2IndexMutex};
1358 auto it = key2Index.find(key);
1359 if (it != key2Index.end()) {
1360 indices.push_front(it->second);
1361 wasMapped = true;
1362 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001363 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001364
1365 for (size_t index : indices) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001366 Cache& cache = Cache::List()[index];
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001367 for (size_t tries = numberOfAttempts; tries > 0; --tries) {
1368 std::shared_ptr<Codec2Client> client{cache.getClient()};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001369 status = predicate(client);
1370 if (status == C2_OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001371 std::scoped_lock lock{key2IndexMutex};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001372 key2Index[key] = index; // update last known client index
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001373 return C2_OK;
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001374 } else if (status == C2_NO_MEMORY) {
1375 return C2_NO_MEMORY;
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001376 } else if (status == C2_TRANSACTION_FAILED) {
1377 LOG(WARNING) << "\"" << key << "\" failed for service \""
1378 << client->getName()
1379 << "\" due to transaction failure. "
1380 << "(Service may have crashed.)"
1381 << (tries > 1 ? " Retrying..." : "");
1382 cache.invalidate();
1383 continue;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001384 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001385 if (wasMapped) {
1386 LOG(INFO) << "\"" << key << "\" became invalid in service \""
1387 << client->getName() << "\". Retrying...";
1388 wasMapped = false;
1389 }
1390 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001391 }
1392 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001393 return status; // return the last status from a valid client
Pawin Vongmasa36653902018-11-15 00:10:25 -08001394}
1395
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001396c2_status_t Codec2Client::CreateComponentByName(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001397 const char* componentName,
1398 const std::shared_ptr<Listener>& listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001399 std::shared_ptr<Component>* component,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001400 std::shared_ptr<Codec2Client>* owner,
1401 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001402 std::string key{"create:"};
1403 key.append(componentName);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001404 c2_status_t status = ForAllServices(
1405 key,
1406 numberOfAttempts,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001407 [owner, component, componentName, &listener](
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001408 const std::shared_ptr<Codec2Client> &client)
1409 -> c2_status_t {
1410 c2_status_t status = client->createComponent(componentName,
1411 listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001412 component);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001413 if (status == C2_OK) {
1414 if (owner) {
1415 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001416 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001417 } else if (status != C2_NOT_FOUND) {
1418 LOG(DEBUG) << "IComponentStore("
1419 << client->getServiceName()
1420 << ")::createComponent(\"" << componentName
1421 << "\") returned status = "
1422 << status << ".";
1423 }
1424 return status;
1425 });
1426 if (status != C2_OK) {
1427 LOG(DEBUG) << "Failed to create component \"" << componentName
1428 << "\" from all known services. "
1429 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001430 }
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001431 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001432}
1433
1434std::shared_ptr<Codec2Client::Interface>
1435 Codec2Client::CreateInterfaceByName(
1436 const char* interfaceName,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001437 std::shared_ptr<Codec2Client>* owner,
1438 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001439 std::string key{"create:"};
1440 key.append(interfaceName);
1441 std::shared_ptr<Interface> interface;
1442 c2_status_t status = ForAllServices(
1443 key,
1444 numberOfAttempts,
1445 [owner, &interface, interfaceName](
1446 const std::shared_ptr<Codec2Client> &client)
1447 -> c2_status_t {
1448 c2_status_t status = client->createInterface(interfaceName,
1449 &interface);
1450 if (status == C2_OK) {
1451 if (owner) {
1452 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001453 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001454 } else if (status != C2_NOT_FOUND) {
1455 LOG(DEBUG) << "IComponentStore("
1456 << client->getServiceName()
1457 << ")::createInterface(\"" << interfaceName
1458 << "\") returned status = "
1459 << status << ".";
1460 }
1461 return status;
1462 });
1463 if (status != C2_OK) {
1464 LOG(DEBUG) << "Failed to create interface \"" << interfaceName
1465 << "\" from all known services. "
1466 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001467 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001468 return interface;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001469}
1470
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001471std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
1472 static std::vector<C2Component::Traits> sList{[]() {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001473 std::vector<C2Component::Traits> list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001474 for (Cache& cache : Cache::List()) {
1475 std::vector<C2Component::Traits> const& traits = cache.getTraits();
1476 list.insert(list.end(), traits.begin(), traits.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001477 }
1478 return list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001479 }()};
1480 return sList;
1481}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001482
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001483std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
1484 char const* serviceName) {
Pawin Vongmasa18588322019-05-18 01:52:13 -07001485 int32_t inputSurfaceSetting = ::android::base::GetIntProperty(
1486 "debug.stagefright.c2inputsurface", int32_t(0));
1487 if (inputSurfaceSetting <= 0) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001488 return nullptr;
1489 }
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001490 size_t index = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001491 if (serviceName) {
1492 index = getServiceIndex(serviceName);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001493 if (index == GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001494 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
1495 << serviceName << "\"";
1496 }
1497 }
1498
1499 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001500 if (index != GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001501 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
1502 if (client->createInputSurface(&inputSurface) == C2_OK) {
1503 return inputSurface;
1504 }
1505 }
1506 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
1507 "from all services...";
1508 for (Cache& cache : Cache::List()) {
1509 std::shared_ptr<Codec2Client> client = cache.getClient();
1510 if (client->createInputSurface(&inputSurface) == C2_OK) {
1511 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
1512 "service \"" << client->getServiceName() << "\"";
1513 return inputSurface;
1514 }
1515 }
1516 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
1517 "from all services";
1518 return nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001519}
1520
1521// Codec2Client::Listener
1522
1523Codec2Client::Listener::~Listener() {
1524}
1525
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001526// Codec2Client::Interface
1527Codec2Client::Interface::Interface(const sp<Base>& base)
1528 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001529 [base]() -> sp<c2_hidl::IConfigurable> {
1530 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001531 base->getConfigurable();
1532 return transResult.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001533 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001534 nullptr;
1535 }()
1536 },
1537 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001538}
1539
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001540// Codec2Client::Component
1541Codec2Client::Component::Component(const sp<Base>& base)
1542 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001543 [base]() -> sp<c2_hidl::IConfigurable> {
1544 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001545 base->getInterface();
1546 if (!transResult1.isOk()) {
1547 return nullptr;
1548 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001549 Return<sp<c2_hidl::IConfigurable>> transResult2 =
1550 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001551 getConfigurable();
1552 return transResult2.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001553 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001554 nullptr;
1555 }()
1556 },
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001557 mBase1_0{base},
1558 mBase1_1{Base1_1::castFrom(base)},
Sungtak Lee8577dab2021-03-12 02:25:50 -08001559 mBase1_2{Base1_2::castFrom(base)},
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001560 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1561 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1562}
1563
1564Codec2Client::Component::Component(const sp<Base1_1>& base)
1565 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001566 [base]() -> sp<c2_hidl::IConfigurable> {
1567 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001568 base->getInterface();
1569 if (!transResult1.isOk()) {
1570 return nullptr;
1571 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001572 Return<sp<c2_hidl::IConfigurable>> transResult2 =
1573 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001574 getConfigurable();
1575 return transResult2.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001576 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001577 nullptr;
1578 }()
1579 },
1580 mBase1_0{base},
1581 mBase1_1{base},
Sungtak Lee8577dab2021-03-12 02:25:50 -08001582 mBase1_2{Base1_2::castFrom(base)},
1583 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1584 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1585}
1586
1587Codec2Client::Component::Component(const sp<Base1_2>& base)
1588 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001589 [base]() -> sp<c2_hidl::IConfigurable> {
1590 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Sungtak Lee8577dab2021-03-12 02:25:50 -08001591 base->getInterface();
1592 if (!transResult1.isOk()) {
1593 return nullptr;
1594 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001595 Return<sp<c2_hidl::IConfigurable>> transResult2 =
1596 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Sungtak Lee8577dab2021-03-12 02:25:50 -08001597 getConfigurable();
1598 return transResult2.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001599 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Sungtak Lee8577dab2021-03-12 02:25:50 -08001600 nullptr;
1601 }()
1602 },
1603 mBase1_0{base},
1604 mBase1_1{base},
1605 mBase1_2{base},
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001606 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1607 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001608}
1609
1610Codec2Client::Component::~Component() {
1611}
1612
1613c2_status_t Codec2Client::Component::createBlockPool(
1614 C2Allocator::id_t id,
1615 C2BlockPool::local_id_t* blockPoolId,
1616 std::shared_ptr<Codec2Client::Configurable>* configurable) {
1617 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001618 Return<void> transStatus = mBase1_0->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001619 static_cast<uint32_t>(id),
1620 [&status, blockPoolId, configurable](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001621 c2_hidl::Status s,
Pawin Vongmasa36653902018-11-15 00:10:25 -08001622 uint64_t pId,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001623 const sp<c2_hidl::IConfigurable>& c) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001624 status = static_cast<c2_status_t>(s);
1625 configurable->reset();
1626 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001627 LOG(DEBUG) << "createBlockPool -- call failed: "
1628 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001629 return;
1630 }
1631 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001632 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001633 });
1634 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001635 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001636 return C2_TRANSACTION_FAILED;
1637 }
1638 return status;
1639}
1640
1641c2_status_t Codec2Client::Component::destroyBlockPool(
1642 C2BlockPool::local_id_t localId) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001643 Return<c2_hidl::Status> transResult = mBase1_0->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001644 static_cast<uint64_t>(localId));
1645 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001646 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001647 return C2_TRANSACTION_FAILED;
1648 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001649 return static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transResult));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001650}
1651
Wonsik Kimab34ed62019-01-31 15:28:46 -08001652void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001653 const std::list<std::unique_ptr<C2Work>> &workItems) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001654 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001655 mOutputBufferQueue->holdBufferQueueBlocks(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001656}
1657
1658c2_status_t Codec2Client::Component::queue(
1659 std::list<std::unique_ptr<C2Work>>* const items) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001660 c2_hidl::WorkBundle workBundle;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001661 if (!objcpy(&workBundle, *items, mBufferPoolSender.get())) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001662 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001663 return C2_TRANSACTION_FAILED;
1664 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001665 Return<c2_hidl::Status> transStatus = mBase1_0->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001666 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001667 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001668 return C2_TRANSACTION_FAILED;
1669 }
1670 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001671 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001672 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001673 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001674 }
1675 return status;
1676}
1677
1678c2_status_t Codec2Client::Component::flush(
1679 C2Component::flush_mode_t mode,
1680 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
1681 (void)mode; // Flush mode isn't supported in HIDL yet.
1682 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001683 Return<void> transStatus = mBase1_0->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001684 [&status, flushedWork](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001685 c2_hidl::Status s, const c2_hidl::WorkBundle& wb) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001686 status = static_cast<c2_status_t>(s);
1687 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001688 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001689 return;
1690 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001691 if (!c2_hidl::utils::objcpy(flushedWork, wb)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001692 status = C2_CORRUPTED;
1693 } else {
1694 status = C2_OK;
1695 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001696 });
1697 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001698 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001699 return C2_TRANSACTION_FAILED;
1700 }
1701
1702 // Indices of flushed work items.
1703 std::vector<uint64_t> flushedIndices;
1704 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
1705 if (work) {
1706 if (work->worklets.empty()
1707 || !work->worklets.back()
1708 || (work->worklets.back()->output.flags &
1709 C2FrameData::FLAG_INCOMPLETE) == 0) {
1710 // input is complete
1711 flushedIndices.emplace_back(
1712 work->input.ordinal.frameIndex.peeku());
1713 }
1714 }
1715 }
1716
Pawin Vongmasa36653902018-11-15 00:10:25 -08001717 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001718 mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001719
1720 return status;
1721}
1722
1723c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001724 Return<c2_hidl::Status> transStatus = mBase1_0->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001725 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1726 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001727 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001728 return C2_TRANSACTION_FAILED;
1729 }
1730 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001731 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001732 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001733 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001734 }
1735 return status;
1736}
1737
1738c2_status_t Codec2Client::Component::start() {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001739 Return<c2_hidl::Status> transStatus = mBase1_0->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001740 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001741 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001742 return C2_TRANSACTION_FAILED;
1743 }
1744 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001745 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001746 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001747 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001748 }
1749 return status;
1750}
1751
1752c2_status_t Codec2Client::Component::stop() {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001753 Return<c2_hidl::Status> transStatus = mBase1_0->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001754 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001755 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001756 return C2_TRANSACTION_FAILED;
1757 }
1758 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001759 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001760 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001761 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001762 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001763 return status;
1764}
1765
1766c2_status_t Codec2Client::Component::reset() {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001767 Return<c2_hidl::Status> transStatus = mBase1_0->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001768 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001769 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001770 return C2_TRANSACTION_FAILED;
1771 }
1772 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001773 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001774 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001775 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001776 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001777 return status;
1778}
1779
1780c2_status_t Codec2Client::Component::release() {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001781 Return<c2_hidl::Status> transStatus = mBase1_0->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001782 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001783 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001784 return C2_TRANSACTION_FAILED;
1785 }
1786 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001787 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001788 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001789 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001790 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001791 return status;
1792}
1793
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001794c2_status_t Codec2Client::Component::configureVideoTunnel(
1795 uint32_t avSyncHwId,
1796 native_handle_t** sidebandHandle) {
1797 *sidebandHandle = nullptr;
1798 if (!mBase1_1) {
1799 return C2_OMITTED;
1800 }
1801 c2_status_t status{};
1802 Return<void> transStatus = mBase1_1->configureVideoTunnel(avSyncHwId,
1803 [&status, sidebandHandle](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001804 c2_hidl::Status s, hardware::hidl_handle const& h) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001805 status = static_cast<c2_status_t>(s);
1806 if (h.getNativeHandle()) {
1807 *sidebandHandle = native_handle_clone(h.getNativeHandle());
1808 }
1809 });
1810 if (!transStatus.isOk()) {
1811 LOG(ERROR) << "configureVideoTunnel -- transaction failed.";
1812 return C2_TRANSACTION_FAILED;
1813 }
1814 return status;
1815}
1816
Pawin Vongmasa36653902018-11-15 00:10:25 -08001817c2_status_t Codec2Client::Component::setOutputSurface(
1818 C2BlockPool::local_id_t blockPoolId,
1819 const sp<IGraphicBufferProducer>& surface,
Sungtak Leedb14cba2021-04-10 00:50:23 -07001820 uint32_t generation,
1821 int maxDequeueCount) {
Sungtak Lee08515812019-06-05 11:16:32 -07001822 uint64_t bqId = 0;
1823 sp<IGraphicBufferProducer> nullIgbp;
1824 sp<HGraphicBufferProducer2> nullHgbp;
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08001825
Sungtak Lee08515812019-06-05 11:16:32 -07001826 sp<HGraphicBufferProducer2> igbp = surface ?
1827 surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
1828 if (surface && !igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001829 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001830 }
1831
Sungtak Leefb579022022-05-10 06:36:15 +00001832 std::scoped_lock lock(mOutputMutex);
Sungtak Leea714f112021-03-16 05:40:03 -07001833 std::shared_ptr<SurfaceSyncObj> syncObj;
1834
Sungtak Lee08515812019-06-05 11:16:32 -07001835 if (!surface) {
Sungtak Leedb14cba2021-04-10 00:50:23 -07001836 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07001837 } else if (surface->getUniqueId(&bqId) != OK) {
1838 LOG(ERROR) << "setOutputSurface -- "
1839 "cannot obtain bufferqueue id.";
1840 bqId = 0;
Sungtak Leedb14cba2021-04-10 00:50:23 -07001841 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07001842 } else {
Sungtak Leedb14cba2021-04-10 00:50:23 -07001843 mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount, mBase1_2 ?
1844 &syncObj : nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07001845 }
Lajos Molnar78aa7c92021-02-18 21:39:01 -08001846
1847 // set consumer bits
1848 // TODO: should this get incorporated into setOutputSurface method so that consumer bits
1849 // can be set atomically?
1850 uint64_t consumerUsage = kDefaultConsumerUsage;
1851 {
1852 if (surface) {
Ian Kasprzak50990272023-08-11 16:31:50 +00001853 int usage = 0;
1854 status_t err = surface->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage);
Lajos Molnar78aa7c92021-02-18 21:39:01 -08001855 if (err != NO_ERROR) {
1856 ALOGD("setOutputSurface -- failed to get consumer usage bits (%d/%s). ignoring",
1857 err, asString(err));
1858 } else {
1859 // Note: we are adding the default usage because components must support
1860 // producing output frames that can be displayed an all output surfaces.
1861
1862 // TODO: do not set usage for tunneled scenario. It is unclear if consumer usage
1863 // is meaningful in a tunneled scenario; on one hand output buffers exist, but
1864 // they do not exist inside of C2 scope. Any buffer usage shall be communicated
1865 // through the sideband channel.
1866
Ian Kasprzak50990272023-08-11 16:31:50 +00001867 // do an unsigned conversion as bit-31 may be 1
1868 consumerUsage = (uint32_t)usage | kDefaultConsumerUsage;
Lajos Molnar78aa7c92021-02-18 21:39:01 -08001869 }
1870 }
1871
1872 C2StreamUsageTuning::output outputUsage{
1873 0u, C2AndroidMemoryUsage::FromGrallocUsage(consumerUsage).expected};
1874 std::vector<std::unique_ptr<C2SettingResult>> failures;
1875 c2_status_t err = config({&outputUsage}, C2_MAY_BLOCK, &failures);
1876 if (err != C2_OK) {
1877 ALOGD("setOutputSurface -- failed to set consumer usage (%d/%s)",
1878 err, asString(err));
1879 }
1880 }
1881 ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx%s",
1882 generation, (long long)consumerUsage, syncObj ? " sync" : "");
Sungtak Lee08515812019-06-05 11:16:32 -07001883
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001884 Return<c2_hidl::Status> transStatus = syncObj ?
Sungtak Leea714f112021-03-16 05:40:03 -07001885 mBase1_2->setOutputSurfaceWithSyncObj(
1886 static_cast<uint64_t>(blockPoolId),
1887 bqId == 0 ? nullHgbp : igbp, *syncObj) :
1888 mBase1_0->setOutputSurface(
1889 static_cast<uint64_t>(blockPoolId),
1890 bqId == 0 ? nullHgbp : igbp);
Lajos Molnar78aa7c92021-02-18 21:39:01 -08001891
Sungtak Lee8e2e2c62023-01-17 18:29:34 +00001892 mOutputBufferQueue->expireOldWaiters();
1893
Pawin Vongmasa36653902018-11-15 00:10:25 -08001894 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001895 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001896 return C2_TRANSACTION_FAILED;
1897 }
1898 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001899 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001900 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001901 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001902 }
Sungtak Leea714f112021-03-16 05:40:03 -07001903 ALOGD("Surface configure completed");
Pawin Vongmasa36653902018-11-15 00:10:25 -08001904 return status;
1905}
1906
1907status_t Codec2Client::Component::queueToOutputSurface(
1908 const C2ConstGraphicBlock& block,
1909 const QueueBufferInput& input,
1910 QueueBufferOutput* output) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001911 return mOutputBufferQueue->outputBuffer(block, input, output);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001912}
1913
Brian Lindahlc953b462023-01-27 16:21:43 -07001914void Codec2Client::Component::pollForRenderedFrames(FrameEventHistoryDelta* delta) {
1915 mOutputBufferQueue->pollForRenderedFrames(delta);
1916}
1917
Sungtak Leea714f112021-03-16 05:40:03 -07001918void Codec2Client::Component::setOutputSurfaceMaxDequeueCount(
1919 int maxDequeueCount) {
1920 mOutputBufferQueue->updateMaxDequeueBufferCount(maxDequeueCount);
1921}
1922
Sungtak Leec7da7a02022-05-05 08:45:33 +00001923void Codec2Client::Component::stopUsingOutputSurface(
1924 C2BlockPool::local_id_t blockPoolId) {
Sungtak Leefb579022022-05-10 06:36:15 +00001925 std::scoped_lock lock(mOutputMutex);
Sungtak Leec7da7a02022-05-05 08:45:33 +00001926 mOutputBufferQueue->stop();
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001927 Return<c2_hidl::Status> transStatus = mBase1_0->setOutputSurface(
Sungtak Leec7da7a02022-05-05 08:45:33 +00001928 static_cast<uint64_t>(blockPoolId), nullptr);
1929 if (!transStatus.isOk()) {
1930 LOG(ERROR) << "setOutputSurface(stopUsingOutputSurface) -- transaction failed.";
1931 } else {
1932 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001933 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Sungtak Leec7da7a02022-05-05 08:45:33 +00001934 if (status != C2_OK) {
1935 LOG(DEBUG) << "setOutputSurface(stopUsingOutputSurface) -- call failed: "
1936 << status << ".";
1937 }
1938 }
Sungtak Lee8e2e2c62023-01-17 18:29:34 +00001939 mOutputBufferQueue->expireOldWaiters();
Sungtak Leec7da7a02022-05-05 08:45:33 +00001940}
1941
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001942c2_status_t Codec2Client::Component::connectToInputSurface(
1943 const std::shared_ptr<InputSurface>& inputSurface,
1944 std::shared_ptr<InputSurfaceConnection>* connection) {
1945 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001946 Return<void> transStatus = mBase1_0->connectToInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001947 inputSurface->mBase,
1948 [&status, connection](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001949 c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001950 status = static_cast<c2_status_t>(s);
1951 if (status != C2_OK) {
1952 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1953 << status << ".";
1954 return;
1955 }
1956 *connection = std::make_shared<InputSurfaceConnection>(c);
1957 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001958 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001959 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001960 return C2_TRANSACTION_FAILED;
1961 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001962 return status;
1963}
1964
1965c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001966 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001967 const sp<HGraphicBufferSource>& source,
1968 std::shared_ptr<InputSurfaceConnection>* connection) {
1969 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001970 Return<void> transStatus = mBase1_0->connectToOmxInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001971 producer, source,
1972 [&status, connection](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001973 c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001974 status = static_cast<c2_status_t>(s);
1975 if (status != C2_OK) {
1976 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1977 << status << ".";
1978 return;
1979 }
1980 *connection = std::make_shared<InputSurfaceConnection>(c);
1981 });
1982 if (!transStatus.isOk()) {
1983 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1984 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001985 }
1986 return status;
1987}
1988
1989c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001990 Return<c2_hidl::Status> transStatus = mBase1_0->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001991 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001992 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001993 return C2_TRANSACTION_FAILED;
1994 }
1995 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001996 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001997 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001998 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1999 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002000 }
2001 return status;
2002}
2003
2004c2_status_t Codec2Client::Component::setDeathListener(
2005 const std::shared_ptr<Component>& component,
2006 const std::shared_ptr<Listener>& listener) {
2007
2008 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
2009 std::weak_ptr<Component> component;
2010 std::weak_ptr<Listener> base;
2011
2012 virtual void serviceDied(
2013 uint64_t /* cookie */,
2014 const wp<::android::hidl::base::V1_0::IBase>& /* who */
2015 ) override {
2016 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
2017 listener->onDeath(component);
2018 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002019 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002020 }
2021 }
2022 };
2023
2024 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
2025 deathRecipient->base = listener;
2026 deathRecipient->component = component;
2027
2028 component->mDeathRecipient = deathRecipient;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002029 Return<bool> transResult = component->mBase1_0->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002030 component->mDeathRecipient, 0);
2031 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002032 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002033 return C2_TRANSACTION_FAILED;
2034 }
2035 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002036 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002037 return C2_CORRUPTED;
2038 }
2039 return C2_OK;
2040}
2041
2042// Codec2Client::InputSurface
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002043Codec2Client::InputSurface::InputSurface(const sp<c2_hidl::IInputSurface>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002044 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002045 [base]() -> sp<c2_hidl::IConfigurable> {
2046 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002047 base->getConfigurable();
2048 return transResult.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002049 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002050 nullptr;
2051 }()
2052 },
2053 mBase{base},
2054 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08002055 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
2056 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002057 base->getGraphicBufferProducer();
2058 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08002059 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002060 nullptr;
2061 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002062}
2063
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002064sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08002065 Codec2Client::InputSurface::getGraphicBufferProducer() const {
2066 return mGraphicBufferProducer;
2067}
2068
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002069sp<c2_hidl::IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002070 return mBase;
2071}
2072
2073// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08002074Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002075 const sp<c2_hidl::IInputSurfaceConnection>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002076 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002077 [base]() -> sp<c2_hidl::IConfigurable> {
2078 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002079 base->getConfigurable();
2080 return transResult.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002081 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002082 nullptr;
2083 }()
2084 },
2085 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002086}
2087
2088c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002089 Return<c2_hidl::Status> transResult = mBase->disconnect();
2090 return static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transResult));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002091}
2092
2093} // namespace android