blob: 97c08064c9e6dea87afb27af7cdbeb209e1b2612 [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
27#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
28#include <android/hardware/media/c2/1.0/IComponent.h>
29#include <android/hardware/media/c2/1.0/IComponentInterface.h>
30#include <android/hardware/media/c2/1.0/IComponentListener.h>
31#include <android/hardware/media/c2/1.0/IComponentStore.h>
32#include <android/hardware/media/c2/1.0/IConfigurable.h>
33#include <android/hidl/manager/1.2/IServiceManager.h>
34
35#include <android-base/properties.h>
36#include <bufferpool/ClientManager.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070037#include <codec2/hidl/1.0/types.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070038#include <codec2/hidl/1.1/types.h>
Sungtak Lee8577dab2021-03-12 02:25:50 -080039#include <codec2/hidl/1.2/types.h>
Sungtak Leea714f112021-03-16 05:40:03 -070040#include <codec2/hidl/output.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070041
42#include <cutils/native_handle.h>
43#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
44#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
Lajos Molnar78aa7c92021-02-18 21:39:01 -080045#include <hardware/gralloc.h> // for GRALLOC_USAGE_*
Pawin Vongmasabf69de92019-10-29 06:21:27 -070046#include <hidl/HidlSupport.h>
Lajos Molnar78aa7c92021-02-18 21:39:01 -080047#include <system/window.h> // for NATIVE_WINDOW_QUERY_*
48#include <media/stagefright/foundation/ADebug.h> // for asString(status_t)
Pawin Vongmasa36653902018-11-15 00:10:25 -080049
Sungtak Leea714f112021-03-16 05:40:03 -070050
Pawin Vongmasa36653902018-11-15 00:10:25 -080051#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 Vongmasabf69de92019-10-29 06:21:27 -070068using namespace ::android::hardware::media::c2::V1_1;
69using namespace ::android::hardware::media::c2::V1_1::utils;
Sungtak Leed3318082018-09-07 15:52:43 -070070using namespace ::android::hardware::media::bufferpool::V2_0;
71using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
Pawin Vongmasa36653902018-11-15 00:10:25 -080072
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080073using HGraphicBufferProducer1 = ::android::hardware::graphics::bufferqueue::
74 V1_0::IGraphicBufferProducer;
75using HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
76 V2_0::IGraphicBufferProducer;
77using B2HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
78 V2_0::utils::B2HGraphicBufferProducer;
79using H2BGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
80 V2_0::utils::H2BGraphicBufferProducer;
Sungtak Leea714f112021-03-16 05:40:03 -070081using ::android::hardware::media::c2::V1_2::SurfaceSyncObj;
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080082
Pawin Vongmasa36653902018-11-15 00:10:25 -080083namespace /* unnamed */ {
84
85// c2_status_t value that corresponds to hwbinder transaction failure.
86constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
87
Lajos Molnar78aa7c92021-02-18 21:39:01 -080088// By default prepare buffer to be displayed on any of the common surfaces
89constexpr uint64_t kDefaultConsumerUsage =
90 (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER);
91
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070092// Searches for a name in GetServiceNames() and returns the index found. If the
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070093// name is not found, the returned index will be equal to
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070094// GetServiceNames().size().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070095size_t getServiceIndex(char const* name) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -070096 std::vector<std::string> const& names = Codec2Client::GetServiceNames();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070097 size_t i = 0;
98 for (; i < names.size(); ++i) {
99 if (name == names[i]) {
100 break;
101 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800102 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700103 return i;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800104}
105
Pawin Vongmasa83d2c552020-03-05 04:36:08 -0800106class Client2Store : public C2ComponentStore {
107 std::shared_ptr<Codec2Client> mClient;
108
109public:
110 Client2Store(std::shared_ptr<Codec2Client> const& client)
111 : mClient(client) { }
112
113 virtual ~Client2Store() = default;
114
115 virtual c2_status_t config_sm(
116 std::vector<C2Param*> const &params,
117 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
118 return mClient->config(params, C2_MAY_BLOCK, failures);
119 };
120
121 virtual c2_status_t copyBuffer(
122 std::shared_ptr<C2GraphicBuffer>,
123 std::shared_ptr<C2GraphicBuffer>) {
124 return C2_OMITTED;
125 }
126
127 virtual c2_status_t createComponent(
128 C2String, std::shared_ptr<C2Component>* const component) {
129 component->reset();
130 return C2_OMITTED;
131 }
132
133 virtual c2_status_t createInterface(
134 C2String, std::shared_ptr<C2ComponentInterface>* const interface) {
135 interface->reset();
136 return C2_OMITTED;
137 }
138
139 virtual c2_status_t query_sm(
140 std::vector<C2Param*> const& stackParams,
141 std::vector<C2Param::Index> const& heapParamIndices,
142 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
143 return mClient->query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
144 }
145
146 virtual c2_status_t querySupportedParams_nb(
147 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
148 return mClient->querySupportedParams(params);
149 }
150
151 virtual c2_status_t querySupportedValues_sm(
152 std::vector<C2FieldSupportedValuesQuery>& fields) const {
153 return mClient->querySupportedValues(fields, C2_MAY_BLOCK);
154 }
155
156 virtual C2String getName() const {
157 return mClient->getName();
158 }
159
160 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const {
161 return mClient->getParamReflector();
162 }
163
164 virtual std::vector<std::shared_ptr<C2Component::Traits const>> listComponents() {
165 return std::vector<std::shared_ptr<C2Component::Traits const>>();
166 }
167};
168
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700169} // unnamed namespace
170
171// This class caches a Codec2Client object and its component traits. The client
172// will be created the first time it is needed, and it can be refreshed if the
173// service dies (by calling invalidate()). The first time listComponents() is
174// called from the client, the result will be cached.
175class Codec2Client::Cache {
176 // Cached client
177 std::shared_ptr<Codec2Client> mClient;
178 mutable std::mutex mClientMutex;
179
180 // Cached component traits
181 std::vector<C2Component::Traits> mTraits;
182 std::once_flag mTraitsInitializationFlag;
183
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700184 // The index of the service. This is based on GetServiceNames().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700185 size_t mIndex;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700186 // Called by s() exactly once to initialize the cache. The index must be a
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700187 // valid index into the vector returned by GetServiceNames(). Calling
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700188 // init(index) will associate the cache to the service with name
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700189 // GetServiceNames()[index].
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700190 void init(size_t index) {
191 mIndex = index;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700192 }
193
194public:
195 Cache() = default;
196
197 // Initializes mClient if needed, then returns mClient.
198 // If the service is unavailable but listed in the manifest, this function
199 // will block indefinitely.
200 std::shared_ptr<Codec2Client> getClient() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700201 std::scoped_lock lock{mClientMutex};
202 if (!mClient) {
203 mClient = Codec2Client::_CreateFromIndex(mIndex);
204 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700205 CHECK(mClient) << "Failed to create Codec2Client to service \""
206 << GetServiceNames()[mIndex] << "\". (Index = "
207 << mIndex << ").";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700208 return mClient;
209 }
210
211 // Causes a subsequent call to getClient() to create a new client. This
212 // function should be called after the service dies.
213 //
214 // Note: This function is called only by ForAllServices().
215 void invalidate() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700216 std::scoped_lock lock{mClientMutex};
217 mClient = nullptr;
218 }
219
220 // Returns a list of traits for components supported by the service. This
221 // list is cached.
222 std::vector<C2Component::Traits> const& getTraits() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700223 std::call_once(mTraitsInitializationFlag, [this]() {
224 bool success{false};
225 // Spin until _listComponents() is successful.
226 while (true) {
227 std::shared_ptr<Codec2Client> client = getClient();
228 mTraits = client->_listComponents(&success);
229 if (success) {
230 break;
231 }
Pawin Vongmasa21617db2020-04-24 06:16:42 -0700232 invalidate();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700233 using namespace std::chrono_literals;
234 static constexpr auto kServiceRetryPeriod = 5s;
235 LOG(INFO) << "Failed to retrieve component traits from service "
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700236 "\"" << GetServiceNames()[mIndex] << "\". "
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700237 "Retrying...";
238 std::this_thread::sleep_for(kServiceRetryPeriod);
239 }
240 });
241 return mTraits;
242 }
243
244 // List() returns the list of all caches.
245 static std::vector<Cache>& List() {
246 static std::vector<Cache> sCaches{[]() {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700247 size_t numServices = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700248 std::vector<Cache> caches(numServices);
249 for (size_t i = 0; i < numServices; ++i) {
250 caches[i].init(i);
251 }
252 return caches;
253 }()};
254 return sCaches;
255 }
256};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800257
258// Codec2ConfigurableClient
259
260const C2String& Codec2ConfigurableClient::getName() const {
261 return mName;
262}
263
Pawin Vongmasa36653902018-11-15 00:10:25 -0800264Codec2ConfigurableClient::Codec2ConfigurableClient(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800265 const sp<IConfigurable>& base)
266 : mBase{base},
267 mName{[base]() -> C2String {
268 C2String outName;
269 Return<void> transStatus = base->getName(
270 [&outName](const hidl_string& name) {
271 outName = name.c_str();
272 });
273 return transStatus.isOk() ? outName : "";
274 }()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800275}
276
277c2_status_t Codec2ConfigurableClient::query(
278 const std::vector<C2Param*> &stackParams,
279 const std::vector<C2Param::Index> &heapParamIndices,
280 c2_blocking_t mayBlock,
281 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
282 hidl_vec<ParamIndex> indices(
283 stackParams.size() + heapParamIndices.size());
284 size_t numIndices = 0;
285 for (C2Param* const& stackParam : stackParams) {
286 if (!stackParam) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800287 LOG(WARNING) << "query -- null stack param encountered.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800288 continue;
289 }
290 indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
291 }
292 size_t numStackIndices = numIndices;
293 for (const C2Param::Index& index : heapParamIndices) {
294 indices[numIndices++] =
295 static_cast<ParamIndex>(static_cast<uint32_t>(index));
296 }
297 indices.resize(numIndices);
298 if (heapParams) {
299 heapParams->reserve(heapParams->size() + numIndices);
300 }
301 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800302 Return<void> transStatus = mBase->query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800303 indices,
304 mayBlock == C2_MAY_BLOCK,
305 [&status, &numStackIndices, &stackParams, heapParams](
306 Status s, const Params& p) {
307 status = static_cast<c2_status_t>(s);
308 if (status != C2_OK && status != C2_BAD_INDEX) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800309 LOG(DEBUG) << "query -- call failed: "
310 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800311 return;
312 }
313 std::vector<C2Param*> paramPointers;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800314 if (!parseParamsBlob(&paramPointers, p)) {
315 LOG(ERROR) << "query -- error while parsing params.";
316 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800317 return;
318 }
319 size_t i = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800320 for (auto it = paramPointers.begin();
321 it != paramPointers.end(); ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800322 C2Param* paramPointer = *it;
323 if (numStackIndices > 0) {
324 --numStackIndices;
325 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800326 LOG(WARNING) << "query -- null stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800327 ++it;
328 continue;
329 }
330 for (; i < stackParams.size() && !stackParams[i]; ) {
331 ++i;
332 }
333 if (i >= stackParams.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800334 LOG(ERROR) << "query -- unexpected error.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800335 status = C2_CORRUPTED;
336 return;
337 }
338 if (stackParams[i]->index() != paramPointer->index()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800339 LOG(WARNING) << "query -- param skipped: "
340 "index = "
341 << stackParams[i]->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800342 stackParams[i++]->invalidate();
343 continue;
344 }
345 if (!stackParams[i++]->updateFrom(*paramPointer)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800346 LOG(WARNING) << "query -- param update failed: "
347 "index = "
348 << paramPointer->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800349 }
350 } else {
351 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800352 LOG(WARNING) << "query -- null heap param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800353 ++it;
354 continue;
355 }
356 if (!heapParams) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800357 LOG(WARNING) << "query -- "
358 "unexpected extra stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800359 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800360 heapParams->emplace_back(
361 C2Param::Copy(*paramPointer));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800362 }
363 }
364 ++it;
365 }
366 });
367 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800368 LOG(ERROR) << "query -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800369 return C2_TRANSACTION_FAILED;
370 }
371 return status;
372}
373
374c2_status_t Codec2ConfigurableClient::config(
375 const std::vector<C2Param*> &params,
376 c2_blocking_t mayBlock,
377 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
378 Params hidlParams;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800379 if (!createParamsBlob(&hidlParams, params)) {
380 LOG(ERROR) << "config -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800381 return C2_TRANSACTION_FAILED;
382 }
383 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800384 Return<void> transStatus = mBase->config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800385 hidlParams,
386 mayBlock == C2_MAY_BLOCK,
387 [&status, &params, failures](
388 Status s,
389 const hidl_vec<SettingResult> f,
390 const Params& o) {
391 status = static_cast<c2_status_t>(s);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800392 if (status != C2_OK && status != C2_BAD_INDEX) {
393 LOG(DEBUG) << "config -- call failed: "
394 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800395 }
396 size_t i = failures->size();
397 failures->resize(i + f.size());
398 for (const SettingResult& sf : f) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800399 if (!objcpy(&(*failures)[i++], sf)) {
400 LOG(ERROR) << "config -- "
401 << "invalid SettingResult returned.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800402 return;
403 }
404 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800405 if (!updateParamsFromBlob(params, o)) {
406 LOG(ERROR) << "config -- "
407 << "failed to parse returned params.";
408 status = C2_CORRUPTED;
409 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800410 });
411 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800412 LOG(ERROR) << "config -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800413 return C2_TRANSACTION_FAILED;
414 }
415 return status;
416}
417
418c2_status_t Codec2ConfigurableClient::querySupportedParams(
419 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
420 // TODO: Cache and query properly!
421 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800422 Return<void> transStatus = mBase->querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800423 std::numeric_limits<uint32_t>::min(),
424 std::numeric_limits<uint32_t>::max(),
425 [&status, params](
426 Status s,
427 const hidl_vec<ParamDescriptor>& p) {
428 status = static_cast<c2_status_t>(s);
429 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800430 LOG(DEBUG) << "querySupportedParams -- call failed: "
431 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800432 return;
433 }
434 size_t i = params->size();
435 params->resize(i + p.size());
436 for (const ParamDescriptor& sp : p) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800437 if (!objcpy(&(*params)[i++], sp)) {
438 LOG(ERROR) << "querySupportedParams -- "
439 << "invalid returned ParamDescriptor.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800440 return;
441 }
442 }
443 });
444 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800445 LOG(ERROR) << "querySupportedParams -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800446 return C2_TRANSACTION_FAILED;
447 }
448 return status;
449}
450
451c2_status_t Codec2ConfigurableClient::querySupportedValues(
452 std::vector<C2FieldSupportedValuesQuery>& fields,
453 c2_blocking_t mayBlock) const {
454 hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
455 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800456 if (!objcpy(&inFields[i], fields[i])) {
457 LOG(ERROR) << "querySupportedValues -- bad input";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800458 return C2_TRANSACTION_FAILED;
459 }
460 }
461
462 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800463 Return<void> transStatus = mBase->querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800464 inFields,
465 mayBlock == C2_MAY_BLOCK,
466 [&status, &inFields, &fields](
467 Status s,
468 const hidl_vec<FieldSupportedValuesQueryResult>& r) {
469 status = static_cast<c2_status_t>(s);
470 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800471 LOG(DEBUG) << "querySupportedValues -- call failed: "
472 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800473 return;
474 }
475 if (r.size() != fields.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800476 LOG(ERROR) << "querySupportedValues -- "
477 "input and output lists "
478 "have different sizes.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800479 status = C2_CORRUPTED;
480 return;
481 }
482 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800483 if (!objcpy(&fields[i], inFields[i], r[i])) {
484 LOG(ERROR) << "querySupportedValues -- "
485 "invalid returned value.";
486 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800487 return;
488 }
489 }
490 });
491 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800492 LOG(ERROR) << "querySupportedValues -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800493 return C2_TRANSACTION_FAILED;
494 }
495 return status;
496}
497
498// Codec2Client::Component::HidlListener
499struct Codec2Client::Component::HidlListener : public IComponentListener {
500 std::weak_ptr<Component> component;
501 std::weak_ptr<Listener> base;
502
503 virtual Return<void> onWorkDone(const WorkBundle& workBundle) override {
504 std::list<std::unique_ptr<C2Work>> workItems;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800505 if (!objcpy(&workItems, workBundle)) {
506 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800507 return Void();
508 }
509 // release input buffers potentially held by the component from queue
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800510 std::shared_ptr<Codec2Client::Component> strongComponent =
511 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800512 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800513 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800514 }
515 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800516 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800517 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800518 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800519 }
520 return Void();
521 }
522
523 virtual Return<void> onTripped(
524 const hidl_vec<SettingResult>& settingResults) override {
525 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
526 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800527 for (size_t i = 0; i < settingResults.size(); ++i) {
528 std::unique_ptr<C2SettingResult> c2SettingResult;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800529 if (!objcpy(&c2SettingResult, settingResults[i])) {
530 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800531 return Void();
532 }
533 c2SettingResults[i] = std::move(c2SettingResult);
534 }
535 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
536 listener->onTripped(component, c2SettingResults);
537 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800538 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800539 }
540 return Void();
541 }
542
543 virtual Return<void> onError(Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800544 LOG(DEBUG) << "onError --"
545 << " status = " << s
546 << ", errorCode = " << errorCode
547 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800548 if (std::shared_ptr<Listener> listener = base.lock()) {
549 listener->onError(component, s == Status::OK ?
550 errorCode : static_cast<c2_status_t>(s));
551 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800552 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800553 }
554 return Void();
555 }
556
557 virtual Return<void> onFramesRendered(
558 const hidl_vec<RenderedFrame>& renderedFrames) override {
559 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800560 if (!listener) {
561 LOG(DEBUG) << "onFramesRendered -- listener died.";
562 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800563 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800564 for (const RenderedFrame& renderedFrame : renderedFrames) {
565 listener->onFrameRendered(
566 renderedFrame.bufferQueueId,
567 renderedFrame.slotId,
568 renderedFrame.timestampNs);
569 }
570 return Void();
571 }
572
573 virtual Return<void> onInputBuffersReleased(
574 const hidl_vec<InputBuffer>& inputBuffers) override {
575 std::shared_ptr<Listener> listener = base.lock();
576 if (!listener) {
577 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
578 return Void();
579 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800580 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800581 LOG(VERBOSE) << "onInputBuffersReleased --"
582 " received death notification of"
583 " input buffer:"
584 " frameIndex = " << inputBuffer.frameIndex
585 << ", bufferIndex = " << inputBuffer.arrayIndex
586 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -0800587 listener->onInputBufferDone(
588 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800589 }
590 return Void();
591 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800592
Pawin Vongmasa36653902018-11-15 00:10:25 -0800593};
594
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700595// Codec2Client::Component::BufferPoolSender
596struct Codec2Client::Component::BufferPoolSender :
597 hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
598 BufferPoolSender()
599 : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
600 }
601};
602
603// Codec2Client::Component::OutputBufferQueue
604struct Codec2Client::Component::OutputBufferQueue :
Sungtak Leea714f112021-03-16 05:40:03 -0700605 hardware::media::c2::OutputBufferQueue {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700606 OutputBufferQueue()
Sungtak Leea714f112021-03-16 05:40:03 -0700607 : hardware::media::c2::OutputBufferQueue() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700608 }
609};
610
Pawin Vongmasa36653902018-11-15 00:10:25 -0800611// Codec2Client
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700612Codec2Client::Codec2Client(sp<Base> const& base,
Sungtak Leec4af3e12023-05-10 07:17:22 +0000613 sp<IConfigurable> const& configurable,
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700614 size_t serviceIndex)
Sungtak Leec4af3e12023-05-10 07:17:22 +0000615 : Configurable{configurable},
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700616 mBase1_0{base},
617 mBase1_1{Base1_1::castFrom(base)},
Sungtak Lee8577dab2021-03-12 02:25:50 -0800618 mBase1_2{Base1_2::castFrom(base)},
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700619 mServiceIndex{serviceIndex} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800620 Return<sp<IClientManager>> transResult = base->getPoolClientManager();
621 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800622 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800623 } else {
624 mHostPoolManager = static_cast<sp<IClientManager>>(transResult);
625 }
626}
627
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700628sp<Codec2Client::Base> const& Codec2Client::getBase() const {
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700629 return mBase1_0;
630}
631
632sp<Codec2Client::Base1_0> const& Codec2Client::getBase1_0() const {
633 return mBase1_0;
634}
635
636sp<Codec2Client::Base1_1> const& Codec2Client::getBase1_1() const {
637 return mBase1_1;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700638}
639
Sungtak Lee8577dab2021-03-12 02:25:50 -0800640sp<Codec2Client::Base1_2> const& Codec2Client::getBase1_2() const {
641 return mBase1_2;
642}
643
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700644std::string const& Codec2Client::getServiceName() const {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700645 return GetServiceNames()[mServiceIndex];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700646}
647
Pawin Vongmasa36653902018-11-15 00:10:25 -0800648c2_status_t Codec2Client::createComponent(
649 const C2String& name,
650 const std::shared_ptr<Codec2Client::Listener>& listener,
651 std::shared_ptr<Codec2Client::Component>* const component) {
652
Pawin Vongmasa36653902018-11-15 00:10:25 -0800653 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800654 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800655 hidlListener->base = listener;
Sungtak Lee8577dab2021-03-12 02:25:50 -0800656 Return<void> transStatus;
657 if (mBase1_2) {
658 transStatus = mBase1_2->createComponent_1_2(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800659 name,
660 hidlListener,
661 ClientManager::getInstance(),
662 [&status, component, hidlListener](
663 Status s,
664 const sp<IComponent>& c) {
665 status = static_cast<c2_status_t>(s);
666 if (status != C2_OK) {
667 return;
668 }
669 *component = std::make_shared<Codec2Client::Component>(c);
670 hidlListener->component = *component;
Sungtak Lee8577dab2021-03-12 02:25:50 -0800671 });
672 }
673 else if (mBase1_1) {
674 transStatus = mBase1_1->createComponent_1_1(
675 name,
676 hidlListener,
677 ClientManager::getInstance(),
678 [&status, component, hidlListener](
679 Status s,
680 const sp<IComponent>& c) {
681 status = static_cast<c2_status_t>(s);
682 if (status != C2_OK) {
683 return;
684 }
685 *component = std::make_shared<Codec2Client::Component>(c);
686 hidlListener->component = *component;
687 });
688 } else if (mBase1_0) { // ver1_0
689 transStatus = mBase1_0->createComponent(
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700690 name,
691 hidlListener,
692 ClientManager::getInstance(),
693 [&status, component, hidlListener](
694 Status s,
695 const sp<hardware::media::c2::V1_0::IComponent>& c) {
696 status = static_cast<c2_status_t>(s);
697 if (status != C2_OK) {
698 return;
699 }
700 *component = std::make_shared<Codec2Client::Component>(c);
701 hidlListener->component = *component;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800702 });
Sungtak Lee8577dab2021-03-12 02:25:50 -0800703 } else {
704 status = C2_CORRUPTED;
705 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800706 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800707 LOG(ERROR) << "createComponent(" << name.c_str()
708 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800709 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800710 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800711 if (status == C2_NOT_FOUND) {
712 LOG(VERBOSE) << "createComponent(" << name.c_str()
713 << ") -- component not found.";
714 } else {
715 LOG(ERROR) << "createComponent(" << name.c_str()
716 << ") -- call failed: " << status << ".";
717 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800718 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800719 } else if (!*component) {
720 LOG(ERROR) << "createComponent(" << name.c_str()
721 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800722 return C2_CORRUPTED;
723 }
724
725 status = (*component)->setDeathListener(*component, listener);
726 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800727 LOG(ERROR) << "createComponent(" << name.c_str()
728 << ") -- failed to set up death listener: "
729 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800730 }
731
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700732 (*component)->mBufferPoolSender->setReceiver(mHostPoolManager);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800733 return status;
734}
735
736c2_status_t Codec2Client::createInterface(
737 const C2String& name,
738 std::shared_ptr<Codec2Client::Interface>* const interface) {
739 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700740 Return<void> transStatus = mBase1_0->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800741 name,
742 [&status, interface](
743 Status s,
744 const sp<IComponentInterface>& i) {
745 status = static_cast<c2_status_t>(s);
746 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800747 return;
748 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800749 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800750 });
751 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800752 LOG(ERROR) << "createInterface(" << name.c_str()
753 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800754 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800755 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800756 if (status == C2_NOT_FOUND) {
757 LOG(VERBOSE) << "createInterface(" << name.c_str()
758 << ") -- component not found.";
759 } else {
760 LOG(ERROR) << "createInterface(" << name.c_str()
761 << ") -- call failed: " << status << ".";
762 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800763 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800764 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800765
Pawin Vongmasa36653902018-11-15 00:10:25 -0800766 return status;
767}
768
769c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800770 std::shared_ptr<InputSurface>* const inputSurface) {
771 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700772 Return<void> transStatus = mBase1_0->createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800773 [&status, inputSurface](
774 Status s,
775 const sp<IInputSurface>& i) {
776 status = static_cast<c2_status_t>(s);
777 if (status != C2_OK) {
778 return;
779 }
780 *inputSurface = std::make_shared<InputSurface>(i);
781 });
782 if (!transStatus.isOk()) {
783 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800784 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800785 } else if (status != C2_OK) {
786 LOG(DEBUG) << "createInputSurface -- call failed: "
787 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800788 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800789 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800790}
791
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700792std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
793 return Cache::List()[mServiceIndex].getTraits();
794}
795
796std::vector<C2Component::Traits> Codec2Client::_listComponents(
797 bool* success) const {
798 std::vector<C2Component::Traits> traits;
799 std::string const& serviceName = getServiceName();
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700800 Return<void> transStatus = mBase1_0->listComponents(
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700801 [&traits, &serviceName](Status s,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800802 const hidl_vec<IComponentStore::ComponentTraits>& t) {
803 if (s != Status::OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700804 LOG(DEBUG) << "_listComponents -- call failed: "
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800805 << static_cast<c2_status_t>(s) << ".";
806 return;
807 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700808 traits.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800809 for (size_t i = 0; i < t.size(); ++i) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700810 if (!objcpy(&traits[i], t[i])) {
811 LOG(ERROR) << "_listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800812 return;
813 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700814 traits[i].owner = serviceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800815 }
816 });
817 if (!transStatus.isOk()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700818 LOG(ERROR) << "_listComponents -- transaction failed.";
819 *success = false;
820 } else {
821 *success = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800822 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700823 return traits;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800824}
825
826c2_status_t Codec2Client::copyBuffer(
827 const std::shared_ptr<C2Buffer>& src,
828 const std::shared_ptr<C2Buffer>& dst) {
829 // TODO: Implement?
830 (void)src;
831 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800832 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800833 return C2_OMITTED;
834}
835
836std::shared_ptr<C2ParamReflector>
837 Codec2Client::getParamReflector() {
838 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
839 // should reflect the HAL API.
840 struct SimpleParamReflector : public C2ParamReflector {
841 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
842 hidl_vec<ParamIndex> indices(1);
843 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
844 std::unique_ptr<C2StructDescriptor> descriptor;
845 Return<void> transStatus = mBase->getStructDescriptors(
846 indices,
847 [&descriptor](
848 Status s,
849 const hidl_vec<StructDescriptor>& sd) {
850 c2_status_t status = static_cast<c2_status_t>(s);
851 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800852 LOG(DEBUG) << "SimpleParamReflector -- "
853 "getStructDescriptors() failed: "
854 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800855 descriptor.reset();
856 return;
857 }
858 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800859 LOG(DEBUG) << "SimpleParamReflector -- "
860 "getStructDescriptors() "
861 "returned vector of size "
862 << sd.size() << ". "
863 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800864 descriptor.reset();
865 return;
866 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800867 if (!objcpy(&descriptor, sd[0])) {
868 LOG(DEBUG) << "SimpleParamReflector -- "
869 "getStructDescriptors() returned "
870 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800871 descriptor.reset();
872 return;
873 }
874 });
Wonsik Kim492fecd2020-11-19 11:14:11 -0800875 if (!transStatus.isOk()) {
876 LOG(DEBUG) << "SimpleParamReflector -- transaction failed: "
877 << transStatus.description();
878 descriptor.reset();
879 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800880 return descriptor;
881 }
882
883 SimpleParamReflector(sp<Base> base)
884 : mBase(base) { }
885
886 sp<Base> mBase;
887 };
888
Pawin Vongmasabf69de92019-10-29 06:21:27 -0700889 return std::make_shared<SimpleParamReflector>(mBase1_0);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800890};
891
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700892std::vector<std::string> const& Codec2Client::GetServiceNames() {
893 static std::vector<std::string> sServiceNames{[]() {
894 using ::android::hardware::media::c2::V1_0::IComponentStore;
895 using ::android::hidl::manager::V1_2::IServiceManager;
896
897 while (true) {
898 sp<IServiceManager> serviceManager = IServiceManager::getService();
899 CHECK(serviceManager) << "Hardware service manager is not running.";
900
901 // There are three categories of services based on names.
902 std::vector<std::string> defaultNames; // Prefixed with "default"
903 std::vector<std::string> vendorNames; // Prefixed with "vendor"
904 std::vector<std::string> otherNames; // Others
905 Return<void> transResult;
906 transResult = serviceManager->listManifestByInterface(
907 IComponentStore::descriptor,
908 [&defaultNames, &vendorNames, &otherNames](
909 hidl_vec<hidl_string> const& instanceNames) {
910 for (hidl_string const& instanceName : instanceNames) {
911 char const* name = instanceName.c_str();
912 if (strncmp(name, "default", 7) == 0) {
913 defaultNames.emplace_back(name);
914 } else if (strncmp(name, "vendor", 6) == 0) {
915 vendorNames.emplace_back(name);
916 } else {
917 otherNames.emplace_back(name);
918 }
919 }
920 });
921 if (transResult.isOk()) {
922 // Sort service names in each category.
923 std::sort(defaultNames.begin(), defaultNames.end());
924 std::sort(vendorNames.begin(), vendorNames.end());
925 std::sort(otherNames.begin(), otherNames.end());
926
927 // Concatenate the three lists in this order: default, vendor,
928 // other.
929 std::vector<std::string>& names = defaultNames;
930 names.reserve(names.size() + vendorNames.size() + otherNames.size());
931 names.insert(names.end(),
932 std::make_move_iterator(vendorNames.begin()),
933 std::make_move_iterator(vendorNames.end()));
934 names.insert(names.end(),
935 std::make_move_iterator(otherNames.begin()),
936 std::make_move_iterator(otherNames.end()));
937
938 // Summarize to logcat.
939 if (names.empty()) {
940 LOG(INFO) << "No Codec2 services declared in the manifest.";
941 } else {
942 std::stringstream stringOutput;
943 stringOutput << "Available Codec2 services:";
944 for (std::string const& name : names) {
945 stringOutput << " \"" << name << "\"";
946 }
947 LOG(INFO) << stringOutput.str();
948 }
949
950 return names;
951 }
952 LOG(ERROR) << "Could not retrieve the list of service instances of "
953 << IComponentStore::descriptor
954 << ". Retrying...";
955 }
956 }()};
957 return sServiceNames;
958}
959
Pawin Vongmasa36653902018-11-15 00:10:25 -0800960std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa83d2c552020-03-05 04:36:08 -0800961 const char* name,
962 bool setAsPreferredCodec2ComponentStore) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700963 size_t index = getServiceIndex(name);
Pawin Vongmasa83d2c552020-03-05 04:36:08 -0800964 if (index == GetServiceNames().size()) {
965 if (setAsPreferredCodec2ComponentStore) {
966 LOG(WARNING) << "CreateFromService(" << name
967 << ") -- preferred C2ComponentStore not set.";
968 }
969 return nullptr;
970 }
971 std::shared_ptr<Codec2Client> client = _CreateFromIndex(index);
972 if (setAsPreferredCodec2ComponentStore) {
973 SetPreferredCodec2ComponentStore(
974 std::make_shared<Client2Store>(client));
975 LOG(INFO) << "CreateFromService(" << name
976 << ") -- service set as preferred C2ComponentStore.";
977 }
978 return client;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800979}
980
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700981std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
982 CreateFromAllServices() {
983 std::vector<std::shared_ptr<Codec2Client>> clients(
984 GetServiceNames().size());
985 for (size_t i = GetServiceNames().size(); i > 0; ) {
986 --i;
987 clients[i] = _CreateFromIndex(i);
988 }
989 return clients;
990}
991
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700992std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700993 std::string const& name = GetServiceNames()[index];
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800994 LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700995 sp<Base> baseStore = Base::getService(name);
996 CHECK(baseStore) << "Codec2 service \"" << name << "\""
997 " inaccessible for unknown reasons.";
Pawin Vongmasa9aac3042020-03-05 02:30:32 -0800998 LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
Sungtak Leec4af3e12023-05-10 07:17:22 +0000999 Return<sp<IConfigurable>> transResult = baseStore->getConfigurable();
1000 CHECK(transResult.isOk()) << "Codec2 service \"" << name << "\""
1001 "does not have IConfigurable.";
1002 sp<IConfigurable> configurable = static_cast<sp<IConfigurable>>(transResult);
1003 return std::make_shared<Codec2Client>(baseStore, configurable, index);
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001004}
1005
1006c2_status_t Codec2Client::ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001007 const std::string &key,
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001008 size_t numberOfAttempts,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001009 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
1010 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001011 c2_status_t status = C2_NO_INIT; // no IComponentStores present
1012
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001013 // Cache the mapping key -> index of Codec2Client in Cache::List().
Pawin Vongmasa36653902018-11-15 00:10:25 -08001014 static std::mutex key2IndexMutex;
1015 static std::map<std::string, size_t> key2Index;
1016
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001017 // By default try all stores. However, try the last known client first. If
1018 // the last known client fails, retry once. We do this by pushing the last
1019 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -08001020 std::deque<size_t> indices;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001021 for (size_t index = Cache::List().size(); index > 0; ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001022 indices.push_front(--index);
1023 }
1024
1025 bool wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001026 {
1027 std::scoped_lock lock{key2IndexMutex};
1028 auto it = key2Index.find(key);
1029 if (it != key2Index.end()) {
1030 indices.push_front(it->second);
1031 wasMapped = true;
1032 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001033 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001034
1035 for (size_t index : indices) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001036 Cache& cache = Cache::List()[index];
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001037 for (size_t tries = numberOfAttempts; tries > 0; --tries) {
1038 std::shared_ptr<Codec2Client> client{cache.getClient()};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001039 status = predicate(client);
1040 if (status == C2_OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001041 std::scoped_lock lock{key2IndexMutex};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001042 key2Index[key] = index; // update last known client index
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001043 return C2_OK;
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001044 } else if (status == C2_NO_MEMORY) {
1045 return C2_NO_MEMORY;
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001046 } else if (status == C2_TRANSACTION_FAILED) {
1047 LOG(WARNING) << "\"" << key << "\" failed for service \""
1048 << client->getName()
1049 << "\" due to transaction failure. "
1050 << "(Service may have crashed.)"
1051 << (tries > 1 ? " Retrying..." : "");
1052 cache.invalidate();
1053 continue;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001054 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001055 if (wasMapped) {
1056 LOG(INFO) << "\"" << key << "\" became invalid in service \""
1057 << client->getName() << "\". Retrying...";
1058 wasMapped = false;
1059 }
1060 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001061 }
1062 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001063 return status; // return the last status from a valid client
Pawin Vongmasa36653902018-11-15 00:10:25 -08001064}
1065
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001066c2_status_t Codec2Client::CreateComponentByName(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001067 const char* componentName,
1068 const std::shared_ptr<Listener>& listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001069 std::shared_ptr<Component>* component,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001070 std::shared_ptr<Codec2Client>* owner,
1071 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001072 std::string key{"create:"};
1073 key.append(componentName);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001074 c2_status_t status = ForAllServices(
1075 key,
1076 numberOfAttempts,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001077 [owner, component, componentName, &listener](
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001078 const std::shared_ptr<Codec2Client> &client)
1079 -> c2_status_t {
1080 c2_status_t status = client->createComponent(componentName,
1081 listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001082 component);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001083 if (status == C2_OK) {
1084 if (owner) {
1085 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001086 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001087 } else if (status != C2_NOT_FOUND) {
1088 LOG(DEBUG) << "IComponentStore("
1089 << client->getServiceName()
1090 << ")::createComponent(\"" << componentName
1091 << "\") returned status = "
1092 << status << ".";
1093 }
1094 return status;
1095 });
1096 if (status != C2_OK) {
1097 LOG(DEBUG) << "Failed to create component \"" << componentName
1098 << "\" from all known services. "
1099 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001100 }
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001101 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001102}
1103
1104std::shared_ptr<Codec2Client::Interface>
1105 Codec2Client::CreateInterfaceByName(
1106 const char* interfaceName,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001107 std::shared_ptr<Codec2Client>* owner,
1108 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001109 std::string key{"create:"};
1110 key.append(interfaceName);
1111 std::shared_ptr<Interface> interface;
1112 c2_status_t status = ForAllServices(
1113 key,
1114 numberOfAttempts,
1115 [owner, &interface, interfaceName](
1116 const std::shared_ptr<Codec2Client> &client)
1117 -> c2_status_t {
1118 c2_status_t status = client->createInterface(interfaceName,
1119 &interface);
1120 if (status == C2_OK) {
1121 if (owner) {
1122 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001123 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001124 } else if (status != C2_NOT_FOUND) {
1125 LOG(DEBUG) << "IComponentStore("
1126 << client->getServiceName()
1127 << ")::createInterface(\"" << interfaceName
1128 << "\") returned status = "
1129 << status << ".";
1130 }
1131 return status;
1132 });
1133 if (status != C2_OK) {
1134 LOG(DEBUG) << "Failed to create interface \"" << interfaceName
1135 << "\" from all known services. "
1136 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001137 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001138 return interface;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001139}
1140
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001141std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
1142 static std::vector<C2Component::Traits> sList{[]() {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001143 std::vector<C2Component::Traits> list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001144 for (Cache& cache : Cache::List()) {
1145 std::vector<C2Component::Traits> const& traits = cache.getTraits();
1146 list.insert(list.end(), traits.begin(), traits.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001147 }
1148 return list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001149 }()};
1150 return sList;
1151}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001152
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001153std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
1154 char const* serviceName) {
Pawin Vongmasa18588322019-05-18 01:52:13 -07001155 int32_t inputSurfaceSetting = ::android::base::GetIntProperty(
1156 "debug.stagefright.c2inputsurface", int32_t(0));
1157 if (inputSurfaceSetting <= 0) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001158 return nullptr;
1159 }
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001160 size_t index = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001161 if (serviceName) {
1162 index = getServiceIndex(serviceName);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001163 if (index == GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001164 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
1165 << serviceName << "\"";
1166 }
1167 }
1168
1169 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001170 if (index != GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001171 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
1172 if (client->createInputSurface(&inputSurface) == C2_OK) {
1173 return inputSurface;
1174 }
1175 }
1176 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
1177 "from all services...";
1178 for (Cache& cache : Cache::List()) {
1179 std::shared_ptr<Codec2Client> client = cache.getClient();
1180 if (client->createInputSurface(&inputSurface) == C2_OK) {
1181 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
1182 "service \"" << client->getServiceName() << "\"";
1183 return inputSurface;
1184 }
1185 }
1186 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
1187 "from all services";
1188 return nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001189}
1190
1191// Codec2Client::Listener
1192
1193Codec2Client::Listener::~Listener() {
1194}
1195
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001196// Codec2Client::Interface
1197Codec2Client::Interface::Interface(const sp<Base>& base)
1198 : Configurable{
1199 [base]() -> sp<IConfigurable> {
1200 Return<sp<IConfigurable>> transResult =
1201 base->getConfigurable();
1202 return transResult.isOk() ?
1203 static_cast<sp<IConfigurable>>(transResult) :
1204 nullptr;
1205 }()
1206 },
1207 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001208}
1209
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001210// Codec2Client::Component
1211Codec2Client::Component::Component(const sp<Base>& base)
1212 : Configurable{
1213 [base]() -> sp<IConfigurable> {
1214 Return<sp<IComponentInterface>> transResult1 =
1215 base->getInterface();
1216 if (!transResult1.isOk()) {
1217 return nullptr;
1218 }
1219 Return<sp<IConfigurable>> transResult2 =
1220 static_cast<sp<IComponentInterface>>(transResult1)->
1221 getConfigurable();
1222 return transResult2.isOk() ?
1223 static_cast<sp<IConfigurable>>(transResult2) :
1224 nullptr;
1225 }()
1226 },
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001227 mBase1_0{base},
1228 mBase1_1{Base1_1::castFrom(base)},
Sungtak Lee8577dab2021-03-12 02:25:50 -08001229 mBase1_2{Base1_2::castFrom(base)},
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001230 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1231 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1232}
1233
1234Codec2Client::Component::Component(const sp<Base1_1>& base)
1235 : Configurable{
1236 [base]() -> sp<IConfigurable> {
1237 Return<sp<IComponentInterface>> transResult1 =
1238 base->getInterface();
1239 if (!transResult1.isOk()) {
1240 return nullptr;
1241 }
1242 Return<sp<IConfigurable>> transResult2 =
1243 static_cast<sp<IComponentInterface>>(transResult1)->
1244 getConfigurable();
1245 return transResult2.isOk() ?
1246 static_cast<sp<IConfigurable>>(transResult2) :
1247 nullptr;
1248 }()
1249 },
1250 mBase1_0{base},
1251 mBase1_1{base},
Sungtak Lee8577dab2021-03-12 02:25:50 -08001252 mBase1_2{Base1_2::castFrom(base)},
1253 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1254 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1255}
1256
1257Codec2Client::Component::Component(const sp<Base1_2>& base)
1258 : Configurable{
1259 [base]() -> sp<IConfigurable> {
1260 Return<sp<IComponentInterface>> transResult1 =
1261 base->getInterface();
1262 if (!transResult1.isOk()) {
1263 return nullptr;
1264 }
1265 Return<sp<IConfigurable>> transResult2 =
1266 static_cast<sp<IComponentInterface>>(transResult1)->
1267 getConfigurable();
1268 return transResult2.isOk() ?
1269 static_cast<sp<IConfigurable>>(transResult2) :
1270 nullptr;
1271 }()
1272 },
1273 mBase1_0{base},
1274 mBase1_1{base},
1275 mBase1_2{base},
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001276 mBufferPoolSender{std::make_unique<BufferPoolSender>()},
1277 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001278}
1279
1280Codec2Client::Component::~Component() {
1281}
1282
1283c2_status_t Codec2Client::Component::createBlockPool(
1284 C2Allocator::id_t id,
1285 C2BlockPool::local_id_t* blockPoolId,
1286 std::shared_ptr<Codec2Client::Configurable>* configurable) {
1287 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001288 Return<void> transStatus = mBase1_0->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001289 static_cast<uint32_t>(id),
1290 [&status, blockPoolId, configurable](
1291 Status s,
1292 uint64_t pId,
1293 const sp<IConfigurable>& c) {
1294 status = static_cast<c2_status_t>(s);
1295 configurable->reset();
1296 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001297 LOG(DEBUG) << "createBlockPool -- call failed: "
1298 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001299 return;
1300 }
1301 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001302 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001303 });
1304 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001305 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001306 return C2_TRANSACTION_FAILED;
1307 }
1308 return status;
1309}
1310
1311c2_status_t Codec2Client::Component::destroyBlockPool(
1312 C2BlockPool::local_id_t localId) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001313 Return<Status> transResult = mBase1_0->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001314 static_cast<uint64_t>(localId));
1315 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001316 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001317 return C2_TRANSACTION_FAILED;
1318 }
1319 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1320}
1321
Wonsik Kimab34ed62019-01-31 15:28:46 -08001322void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001323 const std::list<std::unique_ptr<C2Work>> &workItems) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001324 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001325 mOutputBufferQueue->holdBufferQueueBlocks(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001326}
1327
1328c2_status_t Codec2Client::Component::queue(
1329 std::list<std::unique_ptr<C2Work>>* const items) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001330 WorkBundle workBundle;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001331 if (!objcpy(&workBundle, *items, mBufferPoolSender.get())) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001332 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001333 return C2_TRANSACTION_FAILED;
1334 }
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001335 Return<Status> transStatus = mBase1_0->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001336 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001337 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001338 return C2_TRANSACTION_FAILED;
1339 }
1340 c2_status_t status =
1341 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1342 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001343 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001344 }
1345 return status;
1346}
1347
1348c2_status_t Codec2Client::Component::flush(
1349 C2Component::flush_mode_t mode,
1350 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
1351 (void)mode; // Flush mode isn't supported in HIDL yet.
1352 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001353 Return<void> transStatus = mBase1_0->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001354 [&status, flushedWork](
1355 Status s, const WorkBundle& wb) {
1356 status = static_cast<c2_status_t>(s);
1357 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001358 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001359 return;
1360 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001361 if (!objcpy(flushedWork, wb)) {
1362 status = C2_CORRUPTED;
1363 } else {
1364 status = C2_OK;
1365 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001366 });
1367 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001368 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001369 return C2_TRANSACTION_FAILED;
1370 }
1371
1372 // Indices of flushed work items.
1373 std::vector<uint64_t> flushedIndices;
1374 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
1375 if (work) {
1376 if (work->worklets.empty()
1377 || !work->worklets.back()
1378 || (work->worklets.back()->output.flags &
1379 C2FrameData::FLAG_INCOMPLETE) == 0) {
1380 // input is complete
1381 flushedIndices.emplace_back(
1382 work->input.ordinal.frameIndex.peeku());
1383 }
1384 }
1385 }
1386
Pawin Vongmasa36653902018-11-15 00:10:25 -08001387 // Output bufferqueue-based blocks' lifetime management
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001388 mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001389
1390 return status;
1391}
1392
1393c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001394 Return<Status> transStatus = mBase1_0->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001395 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1396 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001397 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001398 return C2_TRANSACTION_FAILED;
1399 }
1400 c2_status_t status =
1401 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1402 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001403 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001404 }
1405 return status;
1406}
1407
1408c2_status_t Codec2Client::Component::start() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001409 Return<Status> transStatus = mBase1_0->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001410 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001411 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001412 return C2_TRANSACTION_FAILED;
1413 }
1414 c2_status_t status =
1415 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1416 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001417 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001418 }
1419 return status;
1420}
1421
1422c2_status_t Codec2Client::Component::stop() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001423 Return<Status> transStatus = mBase1_0->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001424 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001425 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001426 return C2_TRANSACTION_FAILED;
1427 }
1428 c2_status_t status =
1429 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1430 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001431 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001432 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001433 return status;
1434}
1435
1436c2_status_t Codec2Client::Component::reset() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001437 Return<Status> transStatus = mBase1_0->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001438 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001439 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001440 return C2_TRANSACTION_FAILED;
1441 }
1442 c2_status_t status =
1443 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1444 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001445 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001446 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001447 return status;
1448}
1449
1450c2_status_t Codec2Client::Component::release() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001451 Return<Status> transStatus = mBase1_0->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001452 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001453 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001454 return C2_TRANSACTION_FAILED;
1455 }
1456 c2_status_t status =
1457 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1458 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001459 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001460 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001461 return status;
1462}
1463
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001464c2_status_t Codec2Client::Component::configureVideoTunnel(
1465 uint32_t avSyncHwId,
1466 native_handle_t** sidebandHandle) {
1467 *sidebandHandle = nullptr;
1468 if (!mBase1_1) {
1469 return C2_OMITTED;
1470 }
1471 c2_status_t status{};
1472 Return<void> transStatus = mBase1_1->configureVideoTunnel(avSyncHwId,
1473 [&status, sidebandHandle](
1474 Status s, hardware::hidl_handle const& h) {
1475 status = static_cast<c2_status_t>(s);
1476 if (h.getNativeHandle()) {
1477 *sidebandHandle = native_handle_clone(h.getNativeHandle());
1478 }
1479 });
1480 if (!transStatus.isOk()) {
1481 LOG(ERROR) << "configureVideoTunnel -- transaction failed.";
1482 return C2_TRANSACTION_FAILED;
1483 }
1484 return status;
1485}
1486
Pawin Vongmasa36653902018-11-15 00:10:25 -08001487c2_status_t Codec2Client::Component::setOutputSurface(
1488 C2BlockPool::local_id_t blockPoolId,
1489 const sp<IGraphicBufferProducer>& surface,
Sungtak Leedb14cba2021-04-10 00:50:23 -07001490 uint32_t generation,
1491 int maxDequeueCount) {
Sungtak Lee08515812019-06-05 11:16:32 -07001492 uint64_t bqId = 0;
1493 sp<IGraphicBufferProducer> nullIgbp;
1494 sp<HGraphicBufferProducer2> nullHgbp;
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08001495
Sungtak Lee08515812019-06-05 11:16:32 -07001496 sp<HGraphicBufferProducer2> igbp = surface ?
1497 surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
1498 if (surface && !igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001499 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001500 }
1501
Sungtak Leefb579022022-05-10 06:36:15 +00001502 std::scoped_lock lock(mOutputMutex);
Sungtak Leea714f112021-03-16 05:40:03 -07001503 std::shared_ptr<SurfaceSyncObj> syncObj;
1504
Sungtak Lee08515812019-06-05 11:16:32 -07001505 if (!surface) {
Sungtak Leedb14cba2021-04-10 00:50:23 -07001506 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07001507 } else if (surface->getUniqueId(&bqId) != OK) {
1508 LOG(ERROR) << "setOutputSurface -- "
1509 "cannot obtain bufferqueue id.";
1510 bqId = 0;
Sungtak Leedb14cba2021-04-10 00:50:23 -07001511 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07001512 } else {
Sungtak Leedb14cba2021-04-10 00:50:23 -07001513 mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount, mBase1_2 ?
1514 &syncObj : nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07001515 }
Lajos Molnar78aa7c92021-02-18 21:39:01 -08001516
1517 // set consumer bits
1518 // TODO: should this get incorporated into setOutputSurface method so that consumer bits
1519 // can be set atomically?
1520 uint64_t consumerUsage = kDefaultConsumerUsage;
1521 {
1522 if (surface) {
Sungtak Leedbb4a302023-05-08 17:42:11 +00001523 uint64_t usage = 0;
1524 status_t err = surface->getConsumerUsage(&usage);
Lajos Molnar78aa7c92021-02-18 21:39:01 -08001525 if (err != NO_ERROR) {
1526 ALOGD("setOutputSurface -- failed to get consumer usage bits (%d/%s). ignoring",
1527 err, asString(err));
1528 } else {
1529 // Note: we are adding the default usage because components must support
1530 // producing output frames that can be displayed an all output surfaces.
1531
1532 // TODO: do not set usage for tunneled scenario. It is unclear if consumer usage
1533 // is meaningful in a tunneled scenario; on one hand output buffers exist, but
1534 // they do not exist inside of C2 scope. Any buffer usage shall be communicated
1535 // through the sideband channel.
1536
Sungtak Leedbb4a302023-05-08 17:42:11 +00001537 consumerUsage = usage | kDefaultConsumerUsage;
Lajos Molnar78aa7c92021-02-18 21:39:01 -08001538 }
1539 }
1540
1541 C2StreamUsageTuning::output outputUsage{
1542 0u, C2AndroidMemoryUsage::FromGrallocUsage(consumerUsage).expected};
1543 std::vector<std::unique_ptr<C2SettingResult>> failures;
1544 c2_status_t err = config({&outputUsage}, C2_MAY_BLOCK, &failures);
1545 if (err != C2_OK) {
1546 ALOGD("setOutputSurface -- failed to set consumer usage (%d/%s)",
1547 err, asString(err));
1548 }
1549 }
1550 ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx%s",
1551 generation, (long long)consumerUsage, syncObj ? " sync" : "");
Sungtak Lee08515812019-06-05 11:16:32 -07001552
Sungtak Leea714f112021-03-16 05:40:03 -07001553 Return<Status> transStatus = syncObj ?
1554 mBase1_2->setOutputSurfaceWithSyncObj(
1555 static_cast<uint64_t>(blockPoolId),
1556 bqId == 0 ? nullHgbp : igbp, *syncObj) :
1557 mBase1_0->setOutputSurface(
1558 static_cast<uint64_t>(blockPoolId),
1559 bqId == 0 ? nullHgbp : igbp);
Lajos Molnar78aa7c92021-02-18 21:39:01 -08001560
Sungtak Lee3cc67e72023-05-08 17:00:05 +00001561 mOutputBufferQueue->expireOldWaiters();
1562
Pawin Vongmasa36653902018-11-15 00:10:25 -08001563 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001564 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001565 return C2_TRANSACTION_FAILED;
1566 }
1567 c2_status_t status =
1568 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1569 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001570 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001571 }
Sungtak Leea714f112021-03-16 05:40:03 -07001572 ALOGD("Surface configure completed");
Pawin Vongmasa36653902018-11-15 00:10:25 -08001573 return status;
1574}
1575
1576status_t Codec2Client::Component::queueToOutputSurface(
1577 const C2ConstGraphicBlock& block,
1578 const QueueBufferInput& input,
1579 QueueBufferOutput* output) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001580 return mOutputBufferQueue->outputBuffer(block, input, output);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001581}
1582
Brian Lindahl932bf602023-03-09 11:59:48 -07001583void Codec2Client::Component::pollForRenderedFrames(FrameEventHistoryDelta* delta) {
1584 mOutputBufferQueue->pollForRenderedFrames(delta);
1585}
1586
Sungtak Leea714f112021-03-16 05:40:03 -07001587void Codec2Client::Component::setOutputSurfaceMaxDequeueCount(
1588 int maxDequeueCount) {
1589 mOutputBufferQueue->updateMaxDequeueBufferCount(maxDequeueCount);
1590}
1591
Sungtak Leec7da7a02022-05-05 08:45:33 +00001592void Codec2Client::Component::stopUsingOutputSurface(
1593 C2BlockPool::local_id_t blockPoolId) {
Sungtak Leefb579022022-05-10 06:36:15 +00001594 std::scoped_lock lock(mOutputMutex);
Sungtak Leec7da7a02022-05-05 08:45:33 +00001595 mOutputBufferQueue->stop();
1596 Return<Status> transStatus = mBase1_0->setOutputSurface(
1597 static_cast<uint64_t>(blockPoolId), nullptr);
1598 if (!transStatus.isOk()) {
1599 LOG(ERROR) << "setOutputSurface(stopUsingOutputSurface) -- transaction failed.";
1600 } else {
1601 c2_status_t status =
1602 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1603 if (status != C2_OK) {
1604 LOG(DEBUG) << "setOutputSurface(stopUsingOutputSurface) -- call failed: "
1605 << status << ".";
1606 }
1607 }
Sungtak Lee3cc67e72023-05-08 17:00:05 +00001608 mOutputBufferQueue->expireOldWaiters();
Sungtak Leec7da7a02022-05-05 08:45:33 +00001609}
1610
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001611c2_status_t Codec2Client::Component::connectToInputSurface(
1612 const std::shared_ptr<InputSurface>& inputSurface,
1613 std::shared_ptr<InputSurfaceConnection>* connection) {
1614 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001615 Return<void> transStatus = mBase1_0->connectToInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001616 inputSurface->mBase,
1617 [&status, connection](
1618 Status s, const sp<IInputSurfaceConnection>& c) {
1619 status = static_cast<c2_status_t>(s);
1620 if (status != C2_OK) {
1621 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1622 << status << ".";
1623 return;
1624 }
1625 *connection = std::make_shared<InputSurfaceConnection>(c);
1626 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001627 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001628 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001629 return C2_TRANSACTION_FAILED;
1630 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001631 return status;
1632}
1633
1634c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001635 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001636 const sp<HGraphicBufferSource>& source,
1637 std::shared_ptr<InputSurfaceConnection>* connection) {
1638 c2_status_t status;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001639 Return<void> transStatus = mBase1_0->connectToOmxInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001640 producer, source,
1641 [&status, connection](
1642 Status s, const sp<IInputSurfaceConnection>& c) {
1643 status = static_cast<c2_status_t>(s);
1644 if (status != C2_OK) {
1645 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1646 << status << ".";
1647 return;
1648 }
1649 *connection = std::make_shared<InputSurfaceConnection>(c);
1650 });
1651 if (!transStatus.isOk()) {
1652 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1653 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001654 }
1655 return status;
1656}
1657
1658c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001659 Return<Status> transStatus = mBase1_0->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001660 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001661 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001662 return C2_TRANSACTION_FAILED;
1663 }
1664 c2_status_t status =
1665 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1666 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001667 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1668 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001669 }
1670 return status;
1671}
1672
1673c2_status_t Codec2Client::Component::setDeathListener(
1674 const std::shared_ptr<Component>& component,
1675 const std::shared_ptr<Listener>& listener) {
1676
1677 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1678 std::weak_ptr<Component> component;
1679 std::weak_ptr<Listener> base;
1680
1681 virtual void serviceDied(
1682 uint64_t /* cookie */,
1683 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1684 ) override {
1685 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1686 listener->onDeath(component);
1687 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001688 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001689 }
1690 }
1691 };
1692
1693 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1694 deathRecipient->base = listener;
1695 deathRecipient->component = component;
1696
1697 component->mDeathRecipient = deathRecipient;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001698 Return<bool> transResult = component->mBase1_0->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001699 component->mDeathRecipient, 0);
1700 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001701 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001702 return C2_TRANSACTION_FAILED;
1703 }
1704 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001705 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001706 return C2_CORRUPTED;
1707 }
1708 return C2_OK;
1709}
1710
1711// Codec2Client::InputSurface
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001712Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base)
1713 : Configurable{
1714 [base]() -> sp<IConfigurable> {
1715 Return<sp<IConfigurable>> transResult =
1716 base->getConfigurable();
1717 return transResult.isOk() ?
1718 static_cast<sp<IConfigurable>>(transResult) :
1719 nullptr;
1720 }()
1721 },
1722 mBase{base},
1723 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001724 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
1725 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001726 base->getGraphicBufferProducer();
1727 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001728 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001729 nullptr;
1730 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001731}
1732
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001733sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08001734 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1735 return mGraphicBufferProducer;
1736}
1737
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001738sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001739 return mBase;
1740}
1741
1742// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08001743Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001744 const sp<IInputSurfaceConnection>& base)
1745 : Configurable{
1746 [base]() -> sp<IConfigurable> {
1747 Return<sp<IConfigurable>> transResult =
1748 base->getConfigurable();
1749 return transResult.isOk() ?
1750 static_cast<sp<IConfigurable>>(transResult) :
1751 nullptr;
1752 }()
1753 },
1754 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001755}
1756
1757c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001758 Return<Status> transResult = mBase->disconnect();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001759 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1760}
1761
1762} // namespace android