blob: 3ecbb97cb2baf47d4c9a889f16c6935b73ebc2d1 [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 Kimb80887e2022-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
36#include <android-base/properties.h>
37#include <bufferpool/ClientManager.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070038#include <codec2/hidl/1.0/types.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070039#include <codec2/hidl/1.1/types.h>
Sungtak Lee8577dab2021-03-12 02:25:50 -080040#include <codec2/hidl/1.2/types.h>
Sungtak Leea714f112021-03-16 05:40:03 -070041#include <codec2/hidl/output.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070042
43#include <cutils/native_handle.h>
44#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
45#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
Lajos Molnar78aa7c92021-02-18 21:39:01 -080046#include <hardware/gralloc.h> // for GRALLOC_USAGE_*
Pawin Vongmasabf69de92019-10-29 06:21:27 -070047#include <hidl/HidlSupport.h>
Lajos Molnar78aa7c92021-02-18 21:39:01 -080048#include <system/window.h> // for NATIVE_WINDOW_QUERY_*
49#include <media/stagefright/foundation/ADebug.h> // for asString(status_t)
Pawin Vongmasa36653902018-11-15 00:10:25 -080050
51#include <deque>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070052#include <iterator>
Pawin Vongmasa36653902018-11-15 00:10:25 -080053#include <limits>
54#include <map>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070055#include <mutex>
56#include <sstream>
57#include <thread>
Pawin Vongmasa36653902018-11-15 00:10:25 -080058#include <type_traits>
59#include <vector>
60
Pawin Vongmasa36653902018-11-15 00:10:25 -080061namespace android {
62
63using ::android::hardware::hidl_vec;
64using ::android::hardware::hidl_string;
65using ::android::hardware::Return;
66using ::android::hardware::Void;
Pawin Vongmasa36653902018-11-15 00:10:25 -080067
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080068using HGraphicBufferProducer1 = ::android::hardware::graphics::bufferqueue::
69 V1_0::IGraphicBufferProducer;
70using HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
71 V2_0::IGraphicBufferProducer;
72using B2HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
73 V2_0::utils::B2HGraphicBufferProducer;
74using H2BGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
75 V2_0::utils::H2BGraphicBufferProducer;
Sungtak Leea714f112021-03-16 05:40:03 -070076using ::android::hardware::media::c2::V1_2::SurfaceSyncObj;
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080077
Wonsik Kimb80887e2022-12-12 14:43:00 -080078namespace bufferpool_hidl = ::android::hardware::media::bufferpool::V2_0;
Wonsik Kimb80887e2022-12-12 14:43:00 -080079namespace c2_hidl_base = ::android::hardware::media::c2;
80namespace c2_hidl = ::android::hardware::media::c2::V1_2;
81
82using c2_hidl::utils::operator<<;
83
Pawin Vongmasa36653902018-11-15 00:10:25 -080084namespace /* unnamed */ {
85
86// c2_status_t value that corresponds to hwbinder transaction failure.
87constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
88
Lajos Molnar78aa7c92021-02-18 21:39:01 -080089// By default prepare buffer to be displayed on any of the common surfaces
90constexpr uint64_t kDefaultConsumerUsage =
91 (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER);
92
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070093// Searches for a name in GetServiceNames() and returns the index found. If the
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070094// name is not found, the returned index will be equal to
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070095// GetServiceNames().size().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070096size_t getServiceIndex(char const* name) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070097 std::vector<std::string> const& names = Codec2Client::GetServiceNames();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070098 size_t i = 0;
99 for (; i < names.size(); ++i) {
100 if (name == names[i]) {
101 break;
102 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800103 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700104 return i;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800105}
106
Pawin Vongmasa83d2c552020-03-05 04:36:08 -0800107class Client2Store : public C2ComponentStore {
108 std::shared_ptr<Codec2Client> mClient;
109
110public:
111 Client2Store(std::shared_ptr<Codec2Client> const& client)
112 : mClient(client) { }
113
114 virtual ~Client2Store() = default;
115
116 virtual c2_status_t config_sm(
117 std::vector<C2Param*> const &params,
118 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
119 return mClient->config(params, C2_MAY_BLOCK, failures);
120 };
121
122 virtual c2_status_t copyBuffer(
123 std::shared_ptr<C2GraphicBuffer>,
124 std::shared_ptr<C2GraphicBuffer>) {
125 return C2_OMITTED;
126 }
127
128 virtual c2_status_t createComponent(
129 C2String, std::shared_ptr<C2Component>* const component) {
130 component->reset();
131 return C2_OMITTED;
132 }
133
134 virtual c2_status_t createInterface(
135 C2String, std::shared_ptr<C2ComponentInterface>* const interface) {
136 interface->reset();
137 return C2_OMITTED;
138 }
139
140 virtual c2_status_t query_sm(
141 std::vector<C2Param*> const& stackParams,
142 std::vector<C2Param::Index> const& heapParamIndices,
143 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
144 return mClient->query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
145 }
146
147 virtual c2_status_t querySupportedParams_nb(
148 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
149 return mClient->querySupportedParams(params);
150 }
151
152 virtual c2_status_t querySupportedValues_sm(
153 std::vector<C2FieldSupportedValuesQuery>& fields) const {
154 return mClient->querySupportedValues(fields, C2_MAY_BLOCK);
155 }
156
157 virtual C2String getName() const {
158 return mClient->getName();
159 }
160
161 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const {
162 return mClient->getParamReflector();
163 }
164
165 virtual std::vector<std::shared_ptr<C2Component::Traits const>> listComponents() {
166 return std::vector<std::shared_ptr<C2Component::Traits const>>();
167 }
168};
169
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700170} // unnamed namespace
171
172// This class caches a Codec2Client object and its component traits. The client
173// will be created the first time it is needed, and it can be refreshed if the
174// service dies (by calling invalidate()). The first time listComponents() is
175// called from the client, the result will be cached.
176class Codec2Client::Cache {
177 // Cached client
178 std::shared_ptr<Codec2Client> mClient;
179 mutable std::mutex mClientMutex;
180
181 // Cached component traits
182 std::vector<C2Component::Traits> mTraits;
183 std::once_flag mTraitsInitializationFlag;
184
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700185 // The index of the service. This is based on GetServiceNames().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700186 size_t mIndex;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700187 // Called by s() exactly once to initialize the cache. The index must be a
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700188 // valid index into the vector returned by GetServiceNames(). Calling
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700189 // init(index) will associate the cache to the service with name
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700190 // GetServiceNames()[index].
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700191 void init(size_t index) {
192 mIndex = index;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700193 }
194
195public:
196 Cache() = default;
197
198 // Initializes mClient if needed, then returns mClient.
199 // If the service is unavailable but listed in the manifest, this function
200 // will block indefinitely.
201 std::shared_ptr<Codec2Client> getClient() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700202 std::scoped_lock lock{mClientMutex};
203 if (!mClient) {
204 mClient = Codec2Client::_CreateFromIndex(mIndex);
205 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700206 CHECK(mClient) << "Failed to create Codec2Client to service \""
207 << GetServiceNames()[mIndex] << "\". (Index = "
208 << mIndex << ").";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700209 return mClient;
210 }
211
212 // Causes a subsequent call to getClient() to create a new client. This
213 // function should be called after the service dies.
214 //
215 // Note: This function is called only by ForAllServices().
216 void invalidate() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700217 std::scoped_lock lock{mClientMutex};
218 mClient = nullptr;
219 }
220
221 // Returns a list of traits for components supported by the service. This
222 // list is cached.
223 std::vector<C2Component::Traits> const& getTraits() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700224 std::call_once(mTraitsInitializationFlag, [this]() {
225 bool success{false};
226 // Spin until _listComponents() is successful.
227 while (true) {
228 std::shared_ptr<Codec2Client> client = getClient();
229 mTraits = client->_listComponents(&success);
230 if (success) {
231 break;
232 }
Pawin Vongmasa21617db2020-04-24 06:16:42 -0700233 invalidate();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700234 using namespace std::chrono_literals;
235 static constexpr auto kServiceRetryPeriod = 5s;
236 LOG(INFO) << "Failed to retrieve component traits from service "
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700237 "\"" << GetServiceNames()[mIndex] << "\". "
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700238 "Retrying...";
239 std::this_thread::sleep_for(kServiceRetryPeriod);
240 }
241 });
242 return mTraits;
243 }
244
245 // List() returns the list of all caches.
246 static std::vector<Cache>& List() {
247 static std::vector<Cache> sCaches{[]() {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700248 size_t numServices = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700249 std::vector<Cache> caches(numServices);
250 for (size_t i = 0; i < numServices; ++i) {
251 caches[i].init(i);
252 }
253 return caches;
254 }()};
255 return sCaches;
256 }
257};
Wonsik Kimb80887e2022-12-12 14:43:00 -0800258// Codec2ConfigurableClient::HidlImpl
Pawin Vongmasa36653902018-11-15 00:10:25 -0800259
Wonsik Kimb80887e2022-12-12 14:43:00 -0800260struct Codec2ConfigurableClient::HidlImpl : public Codec2ConfigurableClient::ImplBase {
261 typedef c2_hidl::IConfigurable Base;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800262
Wonsik Kimb80887e2022-12-12 14:43:00 -0800263 // base cannot be null.
264 explicit HidlImpl(const sp<Base>& base);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800265
Wonsik Kimb80887e2022-12-12 14:43:00 -0800266 const C2String& getName() const override {
267 return mName;
268 }
269
270 c2_status_t query(
271 const std::vector<C2Param*>& stackParams,
272 const std::vector<C2Param::Index> &heapParamIndices,
273 c2_blocking_t mayBlock,
274 std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
275
276 c2_status_t config(
277 const std::vector<C2Param*> &params,
278 c2_blocking_t mayBlock,
279 std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
280
281 c2_status_t querySupportedParams(
282 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
283 ) const override;
284
285 c2_status_t querySupportedValues(
286 std::vector<C2FieldSupportedValuesQuery>& fields,
287 c2_blocking_t mayBlock) const override;
288
289private:
290 sp<Base> mBase;
291 const C2String mName;
292};
293
294Codec2ConfigurableClient::HidlImpl::HidlImpl(const sp<Base>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800295 : mBase{base},
296 mName{[base]() -> C2String {
297 C2String outName;
298 Return<void> transStatus = base->getName(
299 [&outName](const hidl_string& name) {
300 outName = name.c_str();
301 });
302 return transStatus.isOk() ? outName : "";
303 }()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800304}
305
Wonsik Kimb80887e2022-12-12 14:43:00 -0800306c2_status_t Codec2ConfigurableClient::HidlImpl::query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800307 const std::vector<C2Param*> &stackParams,
308 const std::vector<C2Param::Index> &heapParamIndices,
309 c2_blocking_t mayBlock,
310 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
Wonsik Kimb80887e2022-12-12 14:43:00 -0800311 hidl_vec<c2_hidl::ParamIndex> indices(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800312 stackParams.size() + heapParamIndices.size());
313 size_t numIndices = 0;
314 for (C2Param* const& stackParam : stackParams) {
315 if (!stackParam) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800316 LOG(WARNING) << "query -- null stack param encountered.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800317 continue;
318 }
Wonsik Kimb80887e2022-12-12 14:43:00 -0800319 indices[numIndices++] = static_cast<c2_hidl::ParamIndex>(stackParam->index());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800320 }
321 size_t numStackIndices = numIndices;
322 for (const C2Param::Index& index : heapParamIndices) {
323 indices[numIndices++] =
Wonsik Kimb80887e2022-12-12 14:43:00 -0800324 static_cast<c2_hidl::ParamIndex>(static_cast<uint32_t>(index));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800325 }
326 indices.resize(numIndices);
327 if (heapParams) {
328 heapParams->reserve(heapParams->size() + numIndices);
329 }
330 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800331 Return<void> transStatus = mBase->query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800332 indices,
333 mayBlock == C2_MAY_BLOCK,
334 [&status, &numStackIndices, &stackParams, heapParams](
Wonsik Kimb80887e2022-12-12 14:43:00 -0800335 c2_hidl::Status s, const c2_hidl::Params& p) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800336 status = static_cast<c2_status_t>(s);
337 if (status != C2_OK && status != C2_BAD_INDEX) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800338 LOG(DEBUG) << "query -- call failed: "
339 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800340 return;
341 }
342 std::vector<C2Param*> paramPointers;
Wonsik Kimb80887e2022-12-12 14:43:00 -0800343 if (!c2_hidl::utils::parseParamsBlob(&paramPointers, p)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800344 LOG(ERROR) << "query -- error while parsing params.";
345 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800346 return;
347 }
348 size_t i = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800349 for (auto it = paramPointers.begin();
350 it != paramPointers.end(); ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800351 C2Param* paramPointer = *it;
352 if (numStackIndices > 0) {
353 --numStackIndices;
354 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800355 LOG(WARNING) << "query -- null stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800356 ++it;
357 continue;
358 }
359 for (; i < stackParams.size() && !stackParams[i]; ) {
360 ++i;
361 }
362 if (i >= stackParams.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800363 LOG(ERROR) << "query -- unexpected error.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800364 status = C2_CORRUPTED;
365 return;
366 }
367 if (stackParams[i]->index() != paramPointer->index()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800368 LOG(WARNING) << "query -- param skipped: "
369 "index = "
370 << stackParams[i]->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800371 stackParams[i++]->invalidate();
372 continue;
373 }
374 if (!stackParams[i++]->updateFrom(*paramPointer)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800375 LOG(WARNING) << "query -- param update failed: "
376 "index = "
377 << paramPointer->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800378 }
379 } else {
380 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800381 LOG(WARNING) << "query -- null heap param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800382 ++it;
383 continue;
384 }
385 if (!heapParams) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800386 LOG(WARNING) << "query -- "
387 "unexpected extra stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800388 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800389 heapParams->emplace_back(
390 C2Param::Copy(*paramPointer));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800391 }
392 }
393 ++it;
394 }
395 });
396 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800397 LOG(ERROR) << "query -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800398 return C2_TRANSACTION_FAILED;
399 }
400 return status;
401}
402
Wonsik Kimb80887e2022-12-12 14:43:00 -0800403c2_status_t Codec2ConfigurableClient::HidlImpl::config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800404 const std::vector<C2Param*> &params,
405 c2_blocking_t mayBlock,
406 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
Wonsik Kimb80887e2022-12-12 14:43:00 -0800407 c2_hidl::Params hidlParams;
408 if (!c2_hidl::utils::createParamsBlob(&hidlParams, params)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800409 LOG(ERROR) << "config -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800410 return C2_TRANSACTION_FAILED;
411 }
412 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800413 Return<void> transStatus = mBase->config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800414 hidlParams,
415 mayBlock == C2_MAY_BLOCK,
416 [&status, &params, failures](
Wonsik Kimb80887e2022-12-12 14:43:00 -0800417 c2_hidl::Status s,
418 const hidl_vec<c2_hidl::SettingResult> f,
419 const c2_hidl::Params& o) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800420 status = static_cast<c2_status_t>(s);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800421 if (status != C2_OK && status != C2_BAD_INDEX) {
422 LOG(DEBUG) << "config -- call failed: "
423 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800424 }
425 size_t i = failures->size();
426 failures->resize(i + f.size());
Wonsik Kimb80887e2022-12-12 14:43:00 -0800427 for (const c2_hidl::SettingResult& sf : f) {
428 if (!c2_hidl::utils::objcpy(&(*failures)[i++], sf)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800429 LOG(ERROR) << "config -- "
430 << "invalid SettingResult returned.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800431 return;
432 }
433 }
Wonsik Kimb80887e2022-12-12 14:43:00 -0800434 if (!c2_hidl::utils::updateParamsFromBlob(params, o)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800435 LOG(ERROR) << "config -- "
436 << "failed to parse returned params.";
437 status = C2_CORRUPTED;
438 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800439 });
440 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800441 LOG(ERROR) << "config -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800442 return C2_TRANSACTION_FAILED;
443 }
444 return status;
445}
446
Wonsik Kimb80887e2022-12-12 14:43:00 -0800447c2_status_t Codec2ConfigurableClient::HidlImpl::querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800448 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
449 // TODO: Cache and query properly!
450 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800451 Return<void> transStatus = mBase->querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800452 std::numeric_limits<uint32_t>::min(),
453 std::numeric_limits<uint32_t>::max(),
454 [&status, params](
Wonsik Kimb80887e2022-12-12 14:43:00 -0800455 c2_hidl::Status s,
456 const hidl_vec<c2_hidl::ParamDescriptor>& p) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800457 status = static_cast<c2_status_t>(s);
458 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800459 LOG(DEBUG) << "querySupportedParams -- call failed: "
460 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800461 return;
462 }
463 size_t i = params->size();
464 params->resize(i + p.size());
Wonsik Kimb80887e2022-12-12 14:43:00 -0800465 for (const c2_hidl::ParamDescriptor& sp : p) {
466 if (!c2_hidl::utils::objcpy(&(*params)[i++], sp)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800467 LOG(ERROR) << "querySupportedParams -- "
468 << "invalid returned ParamDescriptor.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800469 return;
470 }
471 }
472 });
473 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800474 LOG(ERROR) << "querySupportedParams -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800475 return C2_TRANSACTION_FAILED;
476 }
477 return status;
478}
479
Wonsik Kimb80887e2022-12-12 14:43:00 -0800480c2_status_t Codec2ConfigurableClient::HidlImpl::querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800481 std::vector<C2FieldSupportedValuesQuery>& fields,
482 c2_blocking_t mayBlock) const {
Wonsik Kimb80887e2022-12-12 14:43:00 -0800483 hidl_vec<c2_hidl::FieldSupportedValuesQuery> inFields(fields.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800484 for (size_t i = 0; i < fields.size(); ++i) {
Wonsik Kimb80887e2022-12-12 14:43:00 -0800485 if (!c2_hidl::utils::objcpy(&inFields[i], fields[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800486 LOG(ERROR) << "querySupportedValues -- bad input";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800487 return C2_TRANSACTION_FAILED;
488 }
489 }
490
491 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800492 Return<void> transStatus = mBase->querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800493 inFields,
494 mayBlock == C2_MAY_BLOCK,
495 [&status, &inFields, &fields](
Wonsik Kimb80887e2022-12-12 14:43:00 -0800496 c2_hidl::Status s,
497 const hidl_vec<c2_hidl::FieldSupportedValuesQueryResult>& r) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800498 status = static_cast<c2_status_t>(s);
499 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800500 LOG(DEBUG) << "querySupportedValues -- call failed: "
501 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800502 return;
503 }
504 if (r.size() != fields.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800505 LOG(ERROR) << "querySupportedValues -- "
506 "input and output lists "
507 "have different sizes.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800508 status = C2_CORRUPTED;
509 return;
510 }
511 for (size_t i = 0; i < fields.size(); ++i) {
Wonsik Kimb80887e2022-12-12 14:43:00 -0800512 if (!c2_hidl::utils::objcpy(&fields[i], inFields[i], r[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800513 LOG(ERROR) << "querySupportedValues -- "
514 "invalid returned value.";
515 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800516 return;
517 }
518 }
519 });
520 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800521 LOG(ERROR) << "querySupportedValues -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800522 return C2_TRANSACTION_FAILED;
523 }
524 return status;
525}
526
Wonsik Kimb80887e2022-12-12 14:43:00 -0800527// Codec2ConfigurableClient::AidlImpl
528
529struct Codec2ConfigurableClient::AidlImpl : public Codec2ConfigurableClient::ImplBase {
Sungtak Lee29ced4b2023-02-16 00:55:20 +0000530 // TODO: C2AIDL was not landed yet, use c2_aidl when it is landed.
531 typedef c2_hidl::IConfigurable Base;
Wonsik Kimb80887e2022-12-12 14:43:00 -0800532
533 // base cannot be null.
534 explicit AidlImpl(const std::shared_ptr<Base>& base);
535
536 const C2String& getName() const override {
537 return mName;
538 }
539
540 c2_status_t query(
541 const std::vector<C2Param*>& stackParams,
542 const std::vector<C2Param::Index> &heapParamIndices,
543 c2_blocking_t mayBlock,
544 std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
545
546 c2_status_t config(
547 const std::vector<C2Param*> &params,
548 c2_blocking_t mayBlock,
549 std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
550
551 c2_status_t querySupportedParams(
552 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
553 ) const override;
554
555 c2_status_t querySupportedValues(
556 std::vector<C2FieldSupportedValuesQuery>& fields,
557 c2_blocking_t mayBlock) const override;
558
559private:
560 std::shared_ptr<Base> mBase;
561 const C2String mName;
562};
563
564Codec2ConfigurableClient::AidlImpl::AidlImpl(const std::shared_ptr<Base>& base)
565 : mBase{base},
566 mName{[base]() -> C2String {
Sungtak Lee29ced4b2023-02-16 00:55:20 +0000567 // TODO: implementation
568 (void)base;
569 return "";
Wonsik Kimb80887e2022-12-12 14:43:00 -0800570 }()} {
571}
572
573c2_status_t Codec2ConfigurableClient::AidlImpl::query(
574 const std::vector<C2Param*> &stackParams,
575 const std::vector<C2Param::Index> &heapParamIndices,
576 c2_blocking_t mayBlock,
577 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
578 (void)stackParams, (void)heapParamIndices, (void)mayBlock, (void)heapParams;
579 // TODO: implementation
580 return C2_OMITTED;
581}
582
583c2_status_t Codec2ConfigurableClient::AidlImpl::config(
584 const std::vector<C2Param*> &params,
585 c2_blocking_t mayBlock,
586 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
587 (void)params, (void)mayBlock, (void)failures;
588 // TODO: implementation
589 return C2_OMITTED;
590}
591
592c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedParams(
593 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
594 (void)params;
595 // TODO: implementation
596 return C2_OMITTED;
597}
598
599c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedValues(
600 std::vector<C2FieldSupportedValuesQuery>& fields,
601 c2_blocking_t mayBlock) const {
602 (void)fields, (void)mayBlock;
603 // TODO: implementation
604 return C2_OMITTED;
605}
606
607// Codec2ConfigurableClient
608
609Codec2ConfigurableClient::Codec2ConfigurableClient(const sp<HidlBase> &hidlBase)
610 : mImpl(new Codec2ConfigurableClient::HidlImpl(hidlBase)) {
611}
612
Wonsik Kimb80887e2022-12-12 14:43:00 -0800613const C2String& Codec2ConfigurableClient::getName() const {
614 return mImpl->getName();
615}
616
617c2_status_t Codec2ConfigurableClient::query(
618 const std::vector<C2Param*>& stackParams,
619 const std::vector<C2Param::Index> &heapParamIndices,
620 c2_blocking_t mayBlock,
621 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
622 return mImpl->query(stackParams, heapParamIndices, mayBlock, heapParams);
623}
624
625c2_status_t Codec2ConfigurableClient::config(
626 const std::vector<C2Param*> &params,
627 c2_blocking_t mayBlock,
628 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
629 return mImpl->config(params, mayBlock, failures);
630}
631
632c2_status_t Codec2ConfigurableClient::querySupportedParams(
633 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
634 return mImpl->querySupportedParams(params);
635}
636
637c2_status_t Codec2ConfigurableClient::querySupportedValues(
638 std::vector<C2FieldSupportedValuesQuery>& fields,
639 c2_blocking_t mayBlock) const {
640 return mImpl->querySupportedValues(fields, mayBlock);
641}
642
643
Pawin Vongmasa36653902018-11-15 00:10:25 -0800644// Codec2Client::Component::HidlListener
Wonsik Kimb80887e2022-12-12 14:43:00 -0800645struct Codec2Client::Component::HidlListener : public c2_hidl::IComponentListener {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800646 std::weak_ptr<Component> component;
647 std::weak_ptr<Listener> base;
648
Wonsik Kimb80887e2022-12-12 14:43:00 -0800649 virtual Return<void> onWorkDone(const c2_hidl::WorkBundle& workBundle) override {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800650 std::list<std::unique_ptr<C2Work>> workItems;
Wonsik Kimb80887e2022-12-12 14:43:00 -0800651 if (!c2_hidl::utils::objcpy(&workItems, workBundle)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800652 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800653 return Void();
654 }
655 // release input buffers potentially held by the component from queue
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800656 std::shared_ptr<Codec2Client::Component> strongComponent =
657 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800658 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800659 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800660 }
661 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800662 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800663 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800664 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800665 }
666 return Void();
667 }
668
669 virtual Return<void> onTripped(
Wonsik Kimb80887e2022-12-12 14:43:00 -0800670 const hidl_vec<c2_hidl::SettingResult>& settingResults) override {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800671 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
672 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800673 for (size_t i = 0; i < settingResults.size(); ++i) {
674 std::unique_ptr<C2SettingResult> c2SettingResult;
Wonsik Kimb80887e2022-12-12 14:43:00 -0800675 if (!c2_hidl::utils::objcpy(&c2SettingResult, settingResults[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800676 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800677 return Void();
678 }
679 c2SettingResults[i] = std::move(c2SettingResult);
680 }
681 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
682 listener->onTripped(component, c2SettingResults);
683 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800684 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800685 }
686 return Void();
687 }
688
Wonsik Kimb80887e2022-12-12 14:43:00 -0800689 virtual Return<void> onError(c2_hidl::Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800690 LOG(DEBUG) << "onError --"
691 << " status = " << s
692 << ", errorCode = " << errorCode
693 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800694 if (std::shared_ptr<Listener> listener = base.lock()) {
Wonsik Kimb80887e2022-12-12 14:43:00 -0800695 listener->onError(component, s == c2_hidl::Status::OK ?
Pawin Vongmasa36653902018-11-15 00:10:25 -0800696 errorCode : static_cast<c2_status_t>(s));
697 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800698 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800699 }
700 return Void();
701 }
702
703 virtual Return<void> onFramesRendered(
704 const hidl_vec<RenderedFrame>& renderedFrames) override {
705 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800706 if (!listener) {
707 LOG(DEBUG) << "onFramesRendered -- listener died.";
708 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800709 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800710 for (const RenderedFrame& renderedFrame : renderedFrames) {
711 listener->onFrameRendered(
712 renderedFrame.bufferQueueId,
713 renderedFrame.slotId,
714 renderedFrame.timestampNs);
715 }
716 return Void();
717 }
718
719 virtual Return<void> onInputBuffersReleased(
720 const hidl_vec<InputBuffer>& inputBuffers) override {
721 std::shared_ptr<Listener> listener = base.lock();
722 if (!listener) {
723 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
724 return Void();
725 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800726 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800727 LOG(VERBOSE) << "onInputBuffersReleased --"
728 " received death notification of"
729 " input buffer:"
730 " frameIndex = " << inputBuffer.frameIndex
731 << ", bufferIndex = " << inputBuffer.arrayIndex
732 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -0800733 listener->onInputBufferDone(
734 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800735 }
736 return Void();
737 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800738
Pawin Vongmasa36653902018-11-15 00:10:25 -0800739};
740
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700741// Codec2Client::Component::BufferPoolSender
742struct Codec2Client::Component::BufferPoolSender :
743 hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
744 BufferPoolSender()
745 : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
746 }
747};
748
749// Codec2Client::Component::OutputBufferQueue
750struct Codec2Client::Component::OutputBufferQueue :
Sungtak Leea714f112021-03-16 05:40:03 -0700751 hardware::media::c2::OutputBufferQueue {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700752 OutputBufferQueue()
Sungtak Leea714f112021-03-16 05:40:03 -0700753 : hardware::media::c2::OutputBufferQueue() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700754 }
755};
756
Pawin Vongmasa36653902018-11-15 00:10:25 -0800757// Codec2Client
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700758Codec2Client::Codec2Client(sp<Base> const& base,
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700759 size_t serviceIndex)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800760 : Configurable{
Wonsik Kimb80887e2022-12-12 14:43:00 -0800761 [base]() -> sp<c2_hidl::IConfigurable> {
762 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800763 base->getConfigurable();
764 return transResult.isOk() ?
Wonsik Kimb80887e2022-12-12 14:43:00 -0800765 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800766 nullptr;
767 }()
768 },
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700769 mBase1_0{base},
770 mBase1_1{Base1_1::castFrom(base)},
Sungtak Lee8577dab2021-03-12 02:25:50 -0800771 mBase1_2{Base1_2::castFrom(base)},
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700772 mServiceIndex{serviceIndex} {
Wonsik Kimb80887e2022-12-12 14:43:00 -0800773 Return<sp<bufferpool_hidl::IClientManager>> transResult = base->getPoolClientManager();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800774 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800775 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800776 } else {
Wonsik Kimb80887e2022-12-12 14:43:00 -0800777 mHostPoolManager = static_cast<sp<bufferpool_hidl::IClientManager>>(transResult);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800778 }
779}
780
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700781sp<Codec2Client::Base> const& Codec2Client::getBase() const {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700782 return mBase1_0;
783}
784
785sp<Codec2Client::Base1_0> const& Codec2Client::getBase1_0() const {
786 return mBase1_0;
787}
788
789sp<Codec2Client::Base1_1> const& Codec2Client::getBase1_1() const {
790 return mBase1_1;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700791}
792
Sungtak Lee8577dab2021-03-12 02:25:50 -0800793sp<Codec2Client::Base1_2> const& Codec2Client::getBase1_2() const {
794 return mBase1_2;
795}
796
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700797std::string const& Codec2Client::getServiceName() const {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700798 return GetServiceNames()[mServiceIndex];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700799}
800
Pawin Vongmasa36653902018-11-15 00:10:25 -0800801c2_status_t Codec2Client::createComponent(
802 const C2String& name,
803 const std::shared_ptr<Codec2Client::Listener>& listener,
804 std::shared_ptr<Codec2Client::Component>* const component) {
805
Pawin Vongmasa36653902018-11-15 00:10:25 -0800806 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800807 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800808 hidlListener->base = listener;
Sungtak Lee8577dab2021-03-12 02:25:50 -0800809 Return<void> transStatus;
810 if (mBase1_2) {
811 transStatus = mBase1_2->createComponent_1_2(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800812 name,
813 hidlListener,
Wonsik Kimb80887e2022-12-12 14:43:00 -0800814 bufferpool_hidl::implementation::ClientManager::getInstance(),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800815 [&status, component, hidlListener](
Wonsik Kimb80887e2022-12-12 14:43:00 -0800816 c2_hidl::Status s,
817 const sp<c2_hidl::IComponent>& c) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800818 status = static_cast<c2_status_t>(s);
819 if (status != C2_OK) {
820 return;
821 }
822 *component = std::make_shared<Codec2Client::Component>(c);
823 hidlListener->component = *component;
Sungtak Lee8577dab2021-03-12 02:25:50 -0800824 });
825 }
826 else if (mBase1_1) {
827 transStatus = mBase1_1->createComponent_1_1(
828 name,
829 hidlListener,
Wonsik Kimb80887e2022-12-12 14:43:00 -0800830 bufferpool_hidl::implementation::ClientManager::getInstance(),
Sungtak Lee8577dab2021-03-12 02:25:50 -0800831 [&status, component, hidlListener](
Wonsik Kimb80887e2022-12-12 14:43:00 -0800832 c2_hidl::Status s,
833 const sp<c2_hidl_base::V1_1::IComponent>& c) {
Sungtak Lee8577dab2021-03-12 02:25:50 -0800834 status = static_cast<c2_status_t>(s);
835 if (status != C2_OK) {
836 return;
837 }
838 *component = std::make_shared<Codec2Client::Component>(c);
839 hidlListener->component = *component;
840 });
841 } else if (mBase1_0) { // ver1_0
842 transStatus = mBase1_0->createComponent(
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700843 name,
844 hidlListener,
Wonsik Kimb80887e2022-12-12 14:43:00 -0800845 bufferpool_hidl::implementation::ClientManager::getInstance(),
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700846 [&status, component, hidlListener](
Wonsik Kimb80887e2022-12-12 14:43:00 -0800847 c2_hidl::Status s,
848 const sp<c2_hidl_base::V1_0::IComponent>& c) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700849 status = static_cast<c2_status_t>(s);
850 if (status != C2_OK) {
851 return;
852 }
853 *component = std::make_shared<Codec2Client::Component>(c);
854 hidlListener->component = *component;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800855 });
Sungtak Lee8577dab2021-03-12 02:25:50 -0800856 } else {
857 status = C2_CORRUPTED;
858 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800859 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800860 LOG(ERROR) << "createComponent(" << name.c_str()
861 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800862 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800863 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800864 if (status == C2_NOT_FOUND) {
865 LOG(VERBOSE) << "createComponent(" << name.c_str()
866 << ") -- component not found.";
867 } else {
868 LOG(ERROR) << "createComponent(" << name.c_str()
869 << ") -- call failed: " << status << ".";
870 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800871 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800872 } else if (!*component) {
873 LOG(ERROR) << "createComponent(" << name.c_str()
874 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800875 return C2_CORRUPTED;
876 }
877
878 status = (*component)->setDeathListener(*component, listener);
879 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800880 LOG(ERROR) << "createComponent(" << name.c_str()
881 << ") -- failed to set up death listener: "
882 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800883 }
884
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700885 (*component)->mBufferPoolSender->setReceiver(mHostPoolManager);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800886 return status;
887}
888
889c2_status_t Codec2Client::createInterface(
890 const C2String& name,
891 std::shared_ptr<Codec2Client::Interface>* const interface) {
892 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700893 Return<void> transStatus = mBase1_0->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800894 name,
895 [&status, interface](
Wonsik Kimb80887e2022-12-12 14:43:00 -0800896 c2_hidl::Status s,
897 const sp<c2_hidl::IComponentInterface>& i) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800898 status = static_cast<c2_status_t>(s);
899 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800900 return;
901 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800902 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800903 });
904 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800905 LOG(ERROR) << "createInterface(" << name.c_str()
906 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800907 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800908 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800909 if (status == C2_NOT_FOUND) {
910 LOG(VERBOSE) << "createInterface(" << name.c_str()
911 << ") -- component not found.";
912 } else {
913 LOG(ERROR) << "createInterface(" << name.c_str()
914 << ") -- call failed: " << status << ".";
915 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800916 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800917 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800918
Pawin Vongmasa36653902018-11-15 00:10:25 -0800919 return status;
920}
921
922c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800923 std::shared_ptr<InputSurface>* const inputSurface) {
924 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700925 Return<void> transStatus = mBase1_0->createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800926 [&status, inputSurface](
Wonsik Kimb80887e2022-12-12 14:43:00 -0800927 c2_hidl::Status s,
928 const sp<c2_hidl::IInputSurface>& i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800929 status = static_cast<c2_status_t>(s);
930 if (status != C2_OK) {
931 return;
932 }
933 *inputSurface = std::make_shared<InputSurface>(i);
934 });
935 if (!transStatus.isOk()) {
936 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800937 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800938 } else if (status != C2_OK) {
939 LOG(DEBUG) << "createInputSurface -- call failed: "
940 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800941 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800942 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800943}
944
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700945std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
946 return Cache::List()[mServiceIndex].getTraits();
947}
948
949std::vector<C2Component::Traits> Codec2Client::_listComponents(
950 bool* success) const {
951 std::vector<C2Component::Traits> traits;
952 std::string const& serviceName = getServiceName();
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700953 Return<void> transStatus = mBase1_0->listComponents(
Wonsik Kimb80887e2022-12-12 14:43:00 -0800954 [&traits, &serviceName](c2_hidl::Status s,
955 const hidl_vec<c2_hidl::IComponentStore::ComponentTraits>& t) {
956 if (s != c2_hidl::Status::OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700957 LOG(DEBUG) << "_listComponents -- call failed: "
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800958 << static_cast<c2_status_t>(s) << ".";
959 return;
960 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700961 traits.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800962 for (size_t i = 0; i < t.size(); ++i) {
Wonsik Kimb80887e2022-12-12 14:43:00 -0800963 if (!c2_hidl::utils::objcpy(&traits[i], t[i])) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700964 LOG(ERROR) << "_listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800965 return;
966 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700967 traits[i].owner = serviceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800968 }
969 });
970 if (!transStatus.isOk()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700971 LOG(ERROR) << "_listComponents -- transaction failed.";
972 *success = false;
973 } else {
974 *success = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800975 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700976 return traits;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800977}
978
979c2_status_t Codec2Client::copyBuffer(
980 const std::shared_ptr<C2Buffer>& src,
981 const std::shared_ptr<C2Buffer>& dst) {
982 // TODO: Implement?
983 (void)src;
984 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800985 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800986 return C2_OMITTED;
987}
988
989std::shared_ptr<C2ParamReflector>
990 Codec2Client::getParamReflector() {
991 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
992 // should reflect the HAL API.
993 struct SimpleParamReflector : public C2ParamReflector {
994 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
Wonsik Kimb80887e2022-12-12 14:43:00 -0800995 hidl_vec<c2_hidl::ParamIndex> indices(1);
996 indices[0] = static_cast<c2_hidl::ParamIndex>(coreIndex.coreIndex());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800997 std::unique_ptr<C2StructDescriptor> descriptor;
998 Return<void> transStatus = mBase->getStructDescriptors(
999 indices,
1000 [&descriptor](
Wonsik Kimb80887e2022-12-12 14:43:00 -08001001 c2_hidl::Status s,
1002 const hidl_vec<c2_hidl::StructDescriptor>& sd) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001003 c2_status_t status = static_cast<c2_status_t>(s);
1004 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001005 LOG(DEBUG) << "SimpleParamReflector -- "
1006 "getStructDescriptors() failed: "
1007 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001008 descriptor.reset();
1009 return;
1010 }
1011 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001012 LOG(DEBUG) << "SimpleParamReflector -- "
1013 "getStructDescriptors() "
1014 "returned vector of size "
1015 << sd.size() << ". "
1016 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001017 descriptor.reset();
1018 return;
1019 }
Wonsik Kimb80887e2022-12-12 14:43:00 -08001020 if (!c2_hidl::utils::objcpy(&descriptor, sd[0])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001021 LOG(DEBUG) << "SimpleParamReflector -- "
1022 "getStructDescriptors() returned "
1023 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001024 descriptor.reset();
1025 return;
1026 }
1027 });
Wonsik Kim492fecd2020-11-19 11:14:11 -08001028 if (!transStatus.isOk()) {
1029 LOG(DEBUG) << "SimpleParamReflector -- transaction failed: "
1030 << transStatus.description();
1031 descriptor.reset();
1032 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001033 return descriptor;
1034 }
1035
1036 SimpleParamReflector(sp<Base> base)
1037 : mBase(base) { }
1038
1039 sp<Base> mBase;
1040 };
1041
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001042 return std::make_shared<SimpleParamReflector>(mBase1_0);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001043};
1044
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001045std::vector<std::string> const& Codec2Client::GetServiceNames() {
1046 static std::vector<std::string> sServiceNames{[]() {
1047 using ::android::hardware::media::c2::V1_0::IComponentStore;
1048 using ::android::hidl::manager::V1_2::IServiceManager;
1049
1050 while (true) {
1051 sp<IServiceManager> serviceManager = IServiceManager::getService();
1052 CHECK(serviceManager) << "Hardware service manager is not running.";
1053
1054 // There are three categories of services based on names.
1055 std::vector<std::string> defaultNames; // Prefixed with "default"
1056 std::vector<std::string> vendorNames; // Prefixed with "vendor"
1057 std::vector<std::string> otherNames; // Others
1058 Return<void> transResult;
1059 transResult = serviceManager->listManifestByInterface(
1060 IComponentStore::descriptor,
1061 [&defaultNames, &vendorNames, &otherNames](
1062 hidl_vec<hidl_string> const& instanceNames) {
1063 for (hidl_string const& instanceName : instanceNames) {
1064 char const* name = instanceName.c_str();
1065 if (strncmp(name, "default", 7) == 0) {
1066 defaultNames.emplace_back(name);
1067 } else if (strncmp(name, "vendor", 6) == 0) {
1068 vendorNames.emplace_back(name);
1069 } else {
1070 otherNames.emplace_back(name);
1071 }
1072 }
1073 });
1074 if (transResult.isOk()) {
1075 // Sort service names in each category.
1076 std::sort(defaultNames.begin(), defaultNames.end());
1077 std::sort(vendorNames.begin(), vendorNames.end());
1078 std::sort(otherNames.begin(), otherNames.end());
1079
1080 // Concatenate the three lists in this order: default, vendor,
1081 // other.
1082 std::vector<std::string>& names = defaultNames;
1083 names.reserve(names.size() + vendorNames.size() + otherNames.size());
1084 names.insert(names.end(),
1085 std::make_move_iterator(vendorNames.begin()),
1086 std::make_move_iterator(vendorNames.end()));
1087 names.insert(names.end(),
1088 std::make_move_iterator(otherNames.begin()),
1089 std::make_move_iterator(otherNames.end()));
1090
1091 // Summarize to logcat.
1092 if (names.empty()) {
1093 LOG(INFO) << "No Codec2 services declared in the manifest.";
1094 } else {
1095 std::stringstream stringOutput;
1096 stringOutput << "Available Codec2 services:";
1097 for (std::string const& name : names) {
1098 stringOutput << " \"" << name << "\"";
1099 }
1100 LOG(INFO) << stringOutput.str();
1101 }
1102
1103 return names;
1104 }
1105 LOG(ERROR) << "Could not retrieve the list of service instances of "
1106 << IComponentStore::descriptor
1107 << ". Retrying...";
1108 }
1109 }()};
1110 return sServiceNames;
1111}
1112
Pawin Vongmasa36653902018-11-15 00:10:25 -08001113std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa83d2c552020-03-05 04:36:08 -08001114 const char* name,
1115 bool setAsPreferredCodec2ComponentStore) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001116 size_t index = getServiceIndex(name);
Pawin Vongmasa83d2c552020-03-05 04:36:08 -08001117 if (index == GetServiceNames().size()) {
1118 if (setAsPreferredCodec2ComponentStore) {
1119 LOG(WARNING) << "CreateFromService(" << name
1120 << ") -- preferred C2ComponentStore not set.";
1121 }
1122 return nullptr;
1123 }
1124 std::shared_ptr<Codec2Client> client = _CreateFromIndex(index);
1125 if (setAsPreferredCodec2ComponentStore) {
1126 SetPreferredCodec2ComponentStore(
1127 std::make_shared<Client2Store>(client));
1128 LOG(INFO) << "CreateFromService(" << name
1129 << ") -- service set as preferred C2ComponentStore.";
1130 }
1131 return client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001132}
1133
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001134std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
1135 CreateFromAllServices() {
1136 std::vector<std::shared_ptr<Codec2Client>> clients(
1137 GetServiceNames().size());
1138 for (size_t i = GetServiceNames().size(); i > 0; ) {
1139 --i;
1140 clients[i] = _CreateFromIndex(i);
1141 }
1142 return clients;
1143}
1144
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001145std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001146 std::string const& name = GetServiceNames()[index];
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08001147 LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001148 sp<Base> baseStore = Base::getService(name);
1149 CHECK(baseStore) << "Codec2 service \"" << name << "\""
1150 " inaccessible for unknown reasons.";
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08001151 LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001152 return std::make_shared<Codec2Client>(baseStore, index);
1153}
1154
1155c2_status_t Codec2Client::ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001156 const std::string &key,
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001157 size_t numberOfAttempts,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001158 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
1159 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001160 c2_status_t status = C2_NO_INIT; // no IComponentStores present
1161
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001162 // Cache the mapping key -> index of Codec2Client in Cache::List().
Pawin Vongmasa36653902018-11-15 00:10:25 -08001163 static std::mutex key2IndexMutex;
1164 static std::map<std::string, size_t> key2Index;
1165
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001166 // By default try all stores. However, try the last known client first. If
1167 // the last known client fails, retry once. We do this by pushing the last
1168 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -08001169 std::deque<size_t> indices;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001170 for (size_t index = Cache::List().size(); index > 0; ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001171 indices.push_front(--index);
1172 }
1173
1174 bool wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001175 {
1176 std::scoped_lock lock{key2IndexMutex};
1177 auto it = key2Index.find(key);
1178 if (it != key2Index.end()) {
1179 indices.push_front(it->second);
1180 wasMapped = true;
1181 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001182 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001183
1184 for (size_t index : indices) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001185 Cache& cache = Cache::List()[index];
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001186 for (size_t tries = numberOfAttempts; tries > 0; --tries) {
1187 std::shared_ptr<Codec2Client> client{cache.getClient()};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001188 status = predicate(client);
1189 if (status == C2_OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001190 std::scoped_lock lock{key2IndexMutex};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001191 key2Index[key] = index; // update last known client index
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001192 return C2_OK;
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001193 } else if (status == C2_NO_MEMORY) {
1194 return C2_NO_MEMORY;
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001195 } else if (status == C2_TRANSACTION_FAILED) {
1196 LOG(WARNING) << "\"" << key << "\" failed for service \""
1197 << client->getName()
1198 << "\" due to transaction failure. "
1199 << "(Service may have crashed.)"
1200 << (tries > 1 ? " Retrying..." : "");
1201 cache.invalidate();
1202 continue;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001203 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001204 if (wasMapped) {
1205 LOG(INFO) << "\"" << key << "\" became invalid in service \""
1206 << client->getName() << "\". Retrying...";
1207 wasMapped = false;
1208 }
1209 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001210 }
1211 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001212 return status; // return the last status from a valid client
Pawin Vongmasa36653902018-11-15 00:10:25 -08001213}
1214
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001215c2_status_t Codec2Client::CreateComponentByName(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001216 const char* componentName,
1217 const std::shared_ptr<Listener>& listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001218 std::shared_ptr<Component>* component,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001219 std::shared_ptr<Codec2Client>* owner,
1220 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001221 std::string key{"create:"};
1222 key.append(componentName);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001223 c2_status_t status = ForAllServices(
1224 key,
1225 numberOfAttempts,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001226 [owner, component, componentName, &listener](
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001227 const std::shared_ptr<Codec2Client> &client)
1228 -> c2_status_t {
1229 c2_status_t status = client->createComponent(componentName,
1230 listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001231 component);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001232 if (status == C2_OK) {
1233 if (owner) {
1234 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001235 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001236 } else if (status != C2_NOT_FOUND) {
1237 LOG(DEBUG) << "IComponentStore("
1238 << client->getServiceName()
1239 << ")::createComponent(\"" << componentName
1240 << "\") returned status = "
1241 << status << ".";
1242 }
1243 return status;
1244 });
1245 if (status != C2_OK) {
1246 LOG(DEBUG) << "Failed to create component \"" << componentName
1247 << "\" from all known services. "
1248 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001249 }
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001250 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001251}
1252
1253std::shared_ptr<Codec2Client::Interface>
1254 Codec2Client::CreateInterfaceByName(
1255 const char* interfaceName,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001256 std::shared_ptr<Codec2Client>* owner,
1257 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001258 std::string key{"create:"};
1259 key.append(interfaceName);
1260 std::shared_ptr<Interface> interface;
1261 c2_status_t status = ForAllServices(
1262 key,
1263 numberOfAttempts,
1264 [owner, &interface, interfaceName](
1265 const std::shared_ptr<Codec2Client> &client)
1266 -> c2_status_t {
1267 c2_status_t status = client->createInterface(interfaceName,
1268 &interface);
1269 if (status == C2_OK) {
1270 if (owner) {
1271 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001272 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001273 } else if (status != C2_NOT_FOUND) {
1274 LOG(DEBUG) << "IComponentStore("
1275 << client->getServiceName()
1276 << ")::createInterface(\"" << interfaceName
1277 << "\") returned status = "
1278 << status << ".";
1279 }
1280 return status;
1281 });
1282 if (status != C2_OK) {
1283 LOG(DEBUG) << "Failed to create interface \"" << interfaceName
1284 << "\" from all known services. "
1285 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001286 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001287 return interface;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001288}
1289
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001290std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
1291 static std::vector<C2Component::Traits> sList{[]() {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001292 std::vector<C2Component::Traits> list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001293 for (Cache& cache : Cache::List()) {
1294 std::vector<C2Component::Traits> const& traits = cache.getTraits();
1295 list.insert(list.end(), traits.begin(), traits.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001296 }
1297 return list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001298 }()};
1299 return sList;
1300}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001301
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001302std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
1303 char const* serviceName) {
Pawin Vongmasa18588322019-05-18 01:52:13 -07001304 int32_t inputSurfaceSetting = ::android::base::GetIntProperty(
1305 "debug.stagefright.c2inputsurface", int32_t(0));
1306 if (inputSurfaceSetting <= 0) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001307 return nullptr;
1308 }
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001309 size_t index = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001310 if (serviceName) {
1311 index = getServiceIndex(serviceName);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001312 if (index == GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001313 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
1314 << serviceName << "\"";
1315 }
1316 }
1317
1318 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001319 if (index != GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001320 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
1321 if (client->createInputSurface(&inputSurface) == C2_OK) {
1322 return inputSurface;
1323 }
1324 }
1325 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
1326 "from all services...";
1327 for (Cache& cache : Cache::List()) {
1328 std::shared_ptr<Codec2Client> client = cache.getClient();
1329 if (client->createInputSurface(&inputSurface) == C2_OK) {
1330 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
1331 "service \"" << client->getServiceName() << "\"";
1332 return inputSurface;
1333 }
1334 }
1335 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
1336 "from all services";
1337 return nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001338}
1339
1340// Codec2Client::Listener
1341
1342Codec2Client::Listener::~Listener() {
1343}
1344
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001345// Codec2Client::Interface
1346Codec2Client::Interface::Interface(const sp<Base>& base)
1347 : Configurable{
Wonsik Kimb80887e2022-12-12 14:43:00 -08001348 [base]() -> sp<c2_hidl::IConfigurable> {
1349 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001350 base->getConfigurable();
1351 return transResult.isOk() ?
Wonsik Kimb80887e2022-12-12 14:43:00 -08001352 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001353 nullptr;
1354 }()
1355 },
1356 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001357}
1358
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001359// Codec2Client::Component
1360Codec2Client::Component::Component(const sp<Base>& base)
1361 : Configurable{
Wonsik Kimb80887e2022-12-12 14:43:00 -08001362 [base]() -> sp<c2_hidl::IConfigurable> {
1363 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001364 base->getInterface();
1365 if (!transResult1.isOk()) {
1366 return nullptr;
1367 }
Wonsik Kimb80887e2022-12-12 14:43:00 -08001368 Return<sp<c2_hidl::IConfigurable>> transResult2 =
1369 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001370 getConfigurable();
1371 return transResult2.isOk() ?
Wonsik Kimb80887e2022-12-12 14:43:00 -08001372 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001373 nullptr;
1374 }()
1375 },
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001376 mBase1_0{base},
1377 mBase1_1{Base1_1::castFrom(base)},
Sungtak Lee8577dab2021-03-12 02:25:50 -08001378 mBase1_2{Base1_2::castFrom(base)},
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001379 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1380 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1381}
1382
1383Codec2Client::Component::Component(const sp<Base1_1>& base)
1384 : Configurable{
Wonsik Kimb80887e2022-12-12 14:43:00 -08001385 [base]() -> sp<c2_hidl::IConfigurable> {
1386 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001387 base->getInterface();
1388 if (!transResult1.isOk()) {
1389 return nullptr;
1390 }
Wonsik Kimb80887e2022-12-12 14:43:00 -08001391 Return<sp<c2_hidl::IConfigurable>> transResult2 =
1392 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001393 getConfigurable();
1394 return transResult2.isOk() ?
Wonsik Kimb80887e2022-12-12 14:43:00 -08001395 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001396 nullptr;
1397 }()
1398 },
1399 mBase1_0{base},
1400 mBase1_1{base},
Sungtak Lee8577dab2021-03-12 02:25:50 -08001401 mBase1_2{Base1_2::castFrom(base)},
1402 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1403 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1404}
1405
1406Codec2Client::Component::Component(const sp<Base1_2>& base)
1407 : Configurable{
Wonsik Kimb80887e2022-12-12 14:43:00 -08001408 [base]() -> sp<c2_hidl::IConfigurable> {
1409 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Sungtak Lee8577dab2021-03-12 02:25:50 -08001410 base->getInterface();
1411 if (!transResult1.isOk()) {
1412 return nullptr;
1413 }
Wonsik Kimb80887e2022-12-12 14:43:00 -08001414 Return<sp<c2_hidl::IConfigurable>> transResult2 =
1415 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Sungtak Lee8577dab2021-03-12 02:25:50 -08001416 getConfigurable();
1417 return transResult2.isOk() ?
Wonsik Kimb80887e2022-12-12 14:43:00 -08001418 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Sungtak Lee8577dab2021-03-12 02:25:50 -08001419 nullptr;
1420 }()
1421 },
1422 mBase1_0{base},
1423 mBase1_1{base},
1424 mBase1_2{base},
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001425 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1426 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001427}
1428
1429Codec2Client::Component::~Component() {
1430}
1431
1432c2_status_t Codec2Client::Component::createBlockPool(
1433 C2Allocator::id_t id,
1434 C2BlockPool::local_id_t* blockPoolId,
1435 std::shared_ptr<Codec2Client::Configurable>* configurable) {
1436 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001437 Return<void> transStatus = mBase1_0->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001438 static_cast<uint32_t>(id),
1439 [&status, blockPoolId, configurable](
Wonsik Kimb80887e2022-12-12 14:43:00 -08001440 c2_hidl::Status s,
Pawin Vongmasa36653902018-11-15 00:10:25 -08001441 uint64_t pId,
Wonsik Kimb80887e2022-12-12 14:43:00 -08001442 const sp<c2_hidl::IConfigurable>& c) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001443 status = static_cast<c2_status_t>(s);
1444 configurable->reset();
1445 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001446 LOG(DEBUG) << "createBlockPool -- call failed: "
1447 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001448 return;
1449 }
1450 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001451 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001452 });
1453 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001454 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001455 return C2_TRANSACTION_FAILED;
1456 }
1457 return status;
1458}
1459
1460c2_status_t Codec2Client::Component::destroyBlockPool(
1461 C2BlockPool::local_id_t localId) {
Wonsik Kimb80887e2022-12-12 14:43:00 -08001462 Return<c2_hidl::Status> transResult = mBase1_0->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001463 static_cast<uint64_t>(localId));
1464 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001465 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001466 return C2_TRANSACTION_FAILED;
1467 }
Wonsik Kimb80887e2022-12-12 14:43:00 -08001468 return static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transResult));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001469}
1470
Wonsik Kimab34ed62019-01-31 15:28:46 -08001471void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001472 const std::list<std::unique_ptr<C2Work>> &workItems) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001473 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001474 mOutputBufferQueue->holdBufferQueueBlocks(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001475}
1476
1477c2_status_t Codec2Client::Component::queue(
1478 std::list<std::unique_ptr<C2Work>>* const items) {
Wonsik Kimb80887e2022-12-12 14:43:00 -08001479 c2_hidl::WorkBundle workBundle;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001480 if (!objcpy(&workBundle, *items, mBufferPoolSender.get())) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001481 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001482 return C2_TRANSACTION_FAILED;
1483 }
Wonsik Kimb80887e2022-12-12 14:43:00 -08001484 Return<c2_hidl::Status> transStatus = mBase1_0->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001485 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001486 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001487 return C2_TRANSACTION_FAILED;
1488 }
1489 c2_status_t status =
Wonsik Kimb80887e2022-12-12 14:43:00 -08001490 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001491 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001492 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001493 }
1494 return status;
1495}
1496
1497c2_status_t Codec2Client::Component::flush(
1498 C2Component::flush_mode_t mode,
1499 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
1500 (void)mode; // Flush mode isn't supported in HIDL yet.
1501 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001502 Return<void> transStatus = mBase1_0->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001503 [&status, flushedWork](
Wonsik Kimb80887e2022-12-12 14:43:00 -08001504 c2_hidl::Status s, const c2_hidl::WorkBundle& wb) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001505 status = static_cast<c2_status_t>(s);
1506 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001507 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001508 return;
1509 }
Wonsik Kimb80887e2022-12-12 14:43:00 -08001510 if (!c2_hidl::utils::objcpy(flushedWork, wb)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001511 status = C2_CORRUPTED;
1512 } else {
1513 status = C2_OK;
1514 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001515 });
1516 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001517 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001518 return C2_TRANSACTION_FAILED;
1519 }
1520
1521 // Indices of flushed work items.
1522 std::vector<uint64_t> flushedIndices;
1523 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
1524 if (work) {
1525 if (work->worklets.empty()
1526 || !work->worklets.back()
1527 || (work->worklets.back()->output.flags &
1528 C2FrameData::FLAG_INCOMPLETE) == 0) {
1529 // input is complete
1530 flushedIndices.emplace_back(
1531 work->input.ordinal.frameIndex.peeku());
1532 }
1533 }
1534 }
1535
Pawin Vongmasa36653902018-11-15 00:10:25 -08001536 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001537 mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001538
1539 return status;
1540}
1541
1542c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Wonsik Kimb80887e2022-12-12 14:43:00 -08001543 Return<c2_hidl::Status> transStatus = mBase1_0->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001544 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1545 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001546 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001547 return C2_TRANSACTION_FAILED;
1548 }
1549 c2_status_t status =
Wonsik Kimb80887e2022-12-12 14:43:00 -08001550 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001551 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001552 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001553 }
1554 return status;
1555}
1556
1557c2_status_t Codec2Client::Component::start() {
Wonsik Kimb80887e2022-12-12 14:43:00 -08001558 Return<c2_hidl::Status> transStatus = mBase1_0->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001559 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001560 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001561 return C2_TRANSACTION_FAILED;
1562 }
1563 c2_status_t status =
Wonsik Kimb80887e2022-12-12 14:43:00 -08001564 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001565 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001566 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001567 }
1568 return status;
1569}
1570
1571c2_status_t Codec2Client::Component::stop() {
Wonsik Kimb80887e2022-12-12 14:43:00 -08001572 Return<c2_hidl::Status> transStatus = mBase1_0->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001573 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001574 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001575 return C2_TRANSACTION_FAILED;
1576 }
1577 c2_status_t status =
Wonsik Kimb80887e2022-12-12 14:43:00 -08001578 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001579 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001580 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001581 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001582 return status;
1583}
1584
1585c2_status_t Codec2Client::Component::reset() {
Wonsik Kimb80887e2022-12-12 14:43:00 -08001586 Return<c2_hidl::Status> transStatus = mBase1_0->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001587 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001588 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001589 return C2_TRANSACTION_FAILED;
1590 }
1591 c2_status_t status =
Wonsik Kimb80887e2022-12-12 14:43:00 -08001592 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001593 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001594 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001595 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001596 return status;
1597}
1598
1599c2_status_t Codec2Client::Component::release() {
Wonsik Kimb80887e2022-12-12 14:43:00 -08001600 Return<c2_hidl::Status> transStatus = mBase1_0->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001601 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001602 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001603 return C2_TRANSACTION_FAILED;
1604 }
1605 c2_status_t status =
Wonsik Kimb80887e2022-12-12 14:43:00 -08001606 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001607 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001608 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001609 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001610 return status;
1611}
1612
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001613c2_status_t Codec2Client::Component::configureVideoTunnel(
1614 uint32_t avSyncHwId,
1615 native_handle_t** sidebandHandle) {
1616 *sidebandHandle = nullptr;
1617 if (!mBase1_1) {
1618 return C2_OMITTED;
1619 }
1620 c2_status_t status{};
1621 Return<void> transStatus = mBase1_1->configureVideoTunnel(avSyncHwId,
1622 [&status, sidebandHandle](
Wonsik Kimb80887e2022-12-12 14:43:00 -08001623 c2_hidl::Status s, hardware::hidl_handle const& h) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001624 status = static_cast<c2_status_t>(s);
1625 if (h.getNativeHandle()) {
1626 *sidebandHandle = native_handle_clone(h.getNativeHandle());
1627 }
1628 });
1629 if (!transStatus.isOk()) {
1630 LOG(ERROR) << "configureVideoTunnel -- transaction failed.";
1631 return C2_TRANSACTION_FAILED;
1632 }
1633 return status;
1634}
1635
Pawin Vongmasa36653902018-11-15 00:10:25 -08001636c2_status_t Codec2Client::Component::setOutputSurface(
1637 C2BlockPool::local_id_t blockPoolId,
1638 const sp<IGraphicBufferProducer>& surface,
Sungtak Leedb14cba2021-04-10 00:50:23 -07001639 uint32_t generation,
1640 int maxDequeueCount) {
Sungtak Lee08515812019-06-05 11:16:32 -07001641 uint64_t bqId = 0;
1642 sp<IGraphicBufferProducer> nullIgbp;
1643 sp<HGraphicBufferProducer2> nullHgbp;
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08001644
Sungtak Lee08515812019-06-05 11:16:32 -07001645 sp<HGraphicBufferProducer2> igbp = surface ?
1646 surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
1647 if (surface && !igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001648 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001649 }
1650
Sungtak Leefb579022022-05-10 06:36:15 +00001651 std::scoped_lock lock(mOutputMutex);
Sungtak Leea714f112021-03-16 05:40:03 -07001652 std::shared_ptr<SurfaceSyncObj> syncObj;
1653
Sungtak Lee08515812019-06-05 11:16:32 -07001654 if (!surface) {
Sungtak Leedb14cba2021-04-10 00:50:23 -07001655 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07001656 } else if (surface->getUniqueId(&bqId) != OK) {
1657 LOG(ERROR) << "setOutputSurface -- "
1658 "cannot obtain bufferqueue id.";
1659 bqId = 0;
Sungtak Leedb14cba2021-04-10 00:50:23 -07001660 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07001661 } else {
Sungtak Leedb14cba2021-04-10 00:50:23 -07001662 mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount, mBase1_2 ?
1663 &syncObj : nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07001664 }
Lajos Molnar78aa7c92021-02-18 21:39:01 -08001665
1666 // set consumer bits
1667 // TODO: should this get incorporated into setOutputSurface method so that consumer bits
1668 // can be set atomically?
1669 uint64_t consumerUsage = kDefaultConsumerUsage;
1670 {
1671 if (surface) {
Sungtak Lee0cd4fbc2023-02-02 00:59:01 +00001672 uint64_t usage = 0;
1673 status_t err = surface->getConsumerUsage(&usage);
Lajos Molnar78aa7c92021-02-18 21:39:01 -08001674 if (err != NO_ERROR) {
1675 ALOGD("setOutputSurface -- failed to get consumer usage bits (%d/%s). ignoring",
1676 err, asString(err));
1677 } else {
1678 // Note: we are adding the default usage because components must support
1679 // producing output frames that can be displayed an all output surfaces.
1680
1681 // TODO: do not set usage for tunneled scenario. It is unclear if consumer usage
1682 // is meaningful in a tunneled scenario; on one hand output buffers exist, but
1683 // they do not exist inside of C2 scope. Any buffer usage shall be communicated
1684 // through the sideband channel.
1685
Sungtak Lee0cd4fbc2023-02-02 00:59:01 +00001686 consumerUsage = usage | kDefaultConsumerUsage;
Lajos Molnar78aa7c92021-02-18 21:39:01 -08001687 }
1688 }
1689
1690 C2StreamUsageTuning::output outputUsage{
1691 0u, C2AndroidMemoryUsage::FromGrallocUsage(consumerUsage).expected};
1692 std::vector<std::unique_ptr<C2SettingResult>> failures;
1693 c2_status_t err = config({&outputUsage}, C2_MAY_BLOCK, &failures);
1694 if (err != C2_OK) {
1695 ALOGD("setOutputSurface -- failed to set consumer usage (%d/%s)",
1696 err, asString(err));
1697 }
1698 }
1699 ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx%s",
1700 generation, (long long)consumerUsage, syncObj ? " sync" : "");
Sungtak Lee08515812019-06-05 11:16:32 -07001701
Wonsik Kimb80887e2022-12-12 14:43:00 -08001702 Return<c2_hidl::Status> transStatus = syncObj ?
Sungtak Leea714f112021-03-16 05:40:03 -07001703 mBase1_2->setOutputSurfaceWithSyncObj(
1704 static_cast<uint64_t>(blockPoolId),
1705 bqId == 0 ? nullHgbp : igbp, *syncObj) :
1706 mBase1_0->setOutputSurface(
1707 static_cast<uint64_t>(blockPoolId),
1708 bqId == 0 ? nullHgbp : igbp);
Lajos Molnar78aa7c92021-02-18 21:39:01 -08001709
Sungtak Lee7c68c1b2023-01-17 18:29:34 +00001710 mOutputBufferQueue->expireOldWaiters();
1711
Pawin Vongmasa36653902018-11-15 00:10:25 -08001712 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001713 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001714 return C2_TRANSACTION_FAILED;
1715 }
1716 c2_status_t status =
Wonsik Kimb80887e2022-12-12 14:43:00 -08001717 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001718 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001719 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001720 }
Sungtak Leea714f112021-03-16 05:40:03 -07001721 ALOGD("Surface configure completed");
Pawin Vongmasa36653902018-11-15 00:10:25 -08001722 return status;
1723}
1724
1725status_t Codec2Client::Component::queueToOutputSurface(
1726 const C2ConstGraphicBlock& block,
1727 const QueueBufferInput& input,
1728 QueueBufferOutput* output) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001729 return mOutputBufferQueue->outputBuffer(block, input, output);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001730}
1731
Sungtak Leea714f112021-03-16 05:40:03 -07001732void Codec2Client::Component::setOutputSurfaceMaxDequeueCount(
1733 int maxDequeueCount) {
1734 mOutputBufferQueue->updateMaxDequeueBufferCount(maxDequeueCount);
1735}
1736
Sungtak Leec7da7a02022-05-05 08:45:33 +00001737void Codec2Client::Component::stopUsingOutputSurface(
1738 C2BlockPool::local_id_t blockPoolId) {
Sungtak Leefb579022022-05-10 06:36:15 +00001739 std::scoped_lock lock(mOutputMutex);
Sungtak Leec7da7a02022-05-05 08:45:33 +00001740 mOutputBufferQueue->stop();
Wonsik Kimb80887e2022-12-12 14:43:00 -08001741 Return<c2_hidl::Status> transStatus = mBase1_0->setOutputSurface(
Sungtak Leec7da7a02022-05-05 08:45:33 +00001742 static_cast<uint64_t>(blockPoolId), nullptr);
1743 if (!transStatus.isOk()) {
1744 LOG(ERROR) << "setOutputSurface(stopUsingOutputSurface) -- transaction failed.";
1745 } else {
1746 c2_status_t status =
Wonsik Kimb80887e2022-12-12 14:43:00 -08001747 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Sungtak Leec7da7a02022-05-05 08:45:33 +00001748 if (status != C2_OK) {
1749 LOG(DEBUG) << "setOutputSurface(stopUsingOutputSurface) -- call failed: "
1750 << status << ".";
1751 }
1752 }
Sungtak Lee7c68c1b2023-01-17 18:29:34 +00001753 mOutputBufferQueue->expireOldWaiters();
Sungtak Leec7da7a02022-05-05 08:45:33 +00001754}
1755
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001756c2_status_t Codec2Client::Component::connectToInputSurface(
1757 const std::shared_ptr<InputSurface>& inputSurface,
1758 std::shared_ptr<InputSurfaceConnection>* connection) {
1759 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001760 Return<void> transStatus = mBase1_0->connectToInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001761 inputSurface->mBase,
1762 [&status, connection](
Wonsik Kimb80887e2022-12-12 14:43:00 -08001763 c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001764 status = static_cast<c2_status_t>(s);
1765 if (status != C2_OK) {
1766 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1767 << status << ".";
1768 return;
1769 }
1770 *connection = std::make_shared<InputSurfaceConnection>(c);
1771 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001772 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001773 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001774 return C2_TRANSACTION_FAILED;
1775 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001776 return status;
1777}
1778
1779c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001780 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001781 const sp<HGraphicBufferSource>& source,
1782 std::shared_ptr<InputSurfaceConnection>* connection) {
1783 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001784 Return<void> transStatus = mBase1_0->connectToOmxInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001785 producer, source,
1786 [&status, connection](
Wonsik Kimb80887e2022-12-12 14:43:00 -08001787 c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001788 status = static_cast<c2_status_t>(s);
1789 if (status != C2_OK) {
1790 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1791 << status << ".";
1792 return;
1793 }
1794 *connection = std::make_shared<InputSurfaceConnection>(c);
1795 });
1796 if (!transStatus.isOk()) {
1797 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1798 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001799 }
1800 return status;
1801}
1802
1803c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Wonsik Kimb80887e2022-12-12 14:43:00 -08001804 Return<c2_hidl::Status> transStatus = mBase1_0->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001805 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001806 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001807 return C2_TRANSACTION_FAILED;
1808 }
1809 c2_status_t status =
Wonsik Kimb80887e2022-12-12 14:43:00 -08001810 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001811 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001812 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1813 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001814 }
1815 return status;
1816}
1817
1818c2_status_t Codec2Client::Component::setDeathListener(
1819 const std::shared_ptr<Component>& component,
1820 const std::shared_ptr<Listener>& listener) {
1821
1822 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1823 std::weak_ptr<Component> component;
1824 std::weak_ptr<Listener> base;
1825
1826 virtual void serviceDied(
1827 uint64_t /* cookie */,
1828 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1829 ) override {
1830 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1831 listener->onDeath(component);
1832 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001833 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001834 }
1835 }
1836 };
1837
1838 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1839 deathRecipient->base = listener;
1840 deathRecipient->component = component;
1841
1842 component->mDeathRecipient = deathRecipient;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001843 Return<bool> transResult = component->mBase1_0->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001844 component->mDeathRecipient, 0);
1845 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001846 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001847 return C2_TRANSACTION_FAILED;
1848 }
1849 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001850 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001851 return C2_CORRUPTED;
1852 }
1853 return C2_OK;
1854}
1855
1856// Codec2Client::InputSurface
Wonsik Kimb80887e2022-12-12 14:43:00 -08001857Codec2Client::InputSurface::InputSurface(const sp<c2_hidl::IInputSurface>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001858 : Configurable{
Wonsik Kimb80887e2022-12-12 14:43:00 -08001859 [base]() -> sp<c2_hidl::IConfigurable> {
1860 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001861 base->getConfigurable();
1862 return transResult.isOk() ?
Wonsik Kimb80887e2022-12-12 14:43:00 -08001863 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001864 nullptr;
1865 }()
1866 },
1867 mBase{base},
1868 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001869 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
1870 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001871 base->getGraphicBufferProducer();
1872 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001873 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001874 nullptr;
1875 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001876}
1877
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001878sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08001879 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1880 return mGraphicBufferProducer;
1881}
1882
Wonsik Kimb80887e2022-12-12 14:43:00 -08001883sp<c2_hidl::IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001884 return mBase;
1885}
1886
1887// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08001888Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Wonsik Kimb80887e2022-12-12 14:43:00 -08001889 const sp<c2_hidl::IInputSurfaceConnection>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001890 : Configurable{
Wonsik Kimb80887e2022-12-12 14:43:00 -08001891 [base]() -> sp<c2_hidl::IConfigurable> {
1892 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001893 base->getConfigurable();
1894 return transResult.isOk() ?
Wonsik Kimb80887e2022-12-12 14:43:00 -08001895 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001896 nullptr;
1897 }()
1898 },
1899 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001900}
1901
1902c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Wonsik Kimb80887e2022-12-12 14:43:00 -08001903 Return<c2_hidl::Status> transResult = mBase->disconnect();
1904 return static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transResult));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001905}
1906
1907} // namespace android