blob: 458f675dc9834853d01984c9dc989584007dd3e3 [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>
22
23#include <deque>
24#include <limits>
25#include <map>
26#include <type_traits>
27#include <vector>
28
29#include <android-base/properties.h>
30#include <bufferpool/ClientManager.h>
31#include <cutils/native_handle.h>
32#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
33#include <hidl/HidlSupport.h>
34#include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080035
Sungtak Leed3318082018-09-07 15:52:43 -070036#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
Pawin Vongmasad0f0e142018-11-15 03:36:28 -080037#include <android/hardware/media/c2/1.0/IComponent.h>
38#include <android/hardware/media/c2/1.0/IComponentInterface.h>
39#include <android/hardware/media/c2/1.0/IComponentListener.h>
40#include <android/hardware/media/c2/1.0/IComponentStore.h>
41#include <android/hardware/media/c2/1.0/IConfigurable.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080042
43#include <C2Debug.h>
44#include <C2BufferPriv.h>
45#include <C2PlatformSupport.h>
46
47namespace android {
48
49using ::android::hardware::hidl_vec;
50using ::android::hardware::hidl_string;
51using ::android::hardware::Return;
52using ::android::hardware::Void;
53using ::android::TWGraphicBufferProducer;
54
Pawin Vongmasad0f0e142018-11-15 03:36:28 -080055using namespace ::android::hardware::media::c2::V1_0;
56using namespace ::android::hardware::media::c2::V1_0::utils;
Sungtak Leed3318082018-09-07 15:52:43 -070057using namespace ::android::hardware::media::bufferpool::V2_0;
58using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
Pawin Vongmasa36653902018-11-15 00:10:25 -080059
60namespace /* unnamed */ {
61
62// c2_status_t value that corresponds to hwbinder transaction failure.
63constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
64
65// List of known IComponentStore services in the decreasing order of preference.
66constexpr const char* kClientNames[] = {
67 "default",
68 "software",
69 };
70
71// Number of known IComponentStore services.
72constexpr size_t kNumClients = std::extent<decltype(kClientNames)>::value;
73
74typedef std::array<std::shared_ptr<Codec2Client>, kNumClients> ClientList;
75
76// Convenience methods to obtain known clients.
77std::shared_ptr<Codec2Client> getClient(size_t index) {
Pawin Vongmasae55ed3f2018-11-28 03:39:57 -080078 uint32_t serviceMask = ::android::base::GetUintProperty(
79 "debug.media.codec2", uint32_t(0));
80 return Codec2Client::CreateFromService(
81 kClientNames[index],
82 (serviceMask & (1 << index)) != 0);
Pawin Vongmasa36653902018-11-15 00:10:25 -080083}
84
85ClientList getClientList() {
86 ClientList list;
87 for (size_t i = 0; i < list.size(); ++i) {
88 list[i] = getClient(i);
89 }
90 return list;
91}
92
93} // unnamed
94
95// Codec2ConfigurableClient
96
97const C2String& Codec2ConfigurableClient::getName() const {
98 return mName;
99}
100
Pawin Vongmasa36653902018-11-15 00:10:25 -0800101Codec2ConfigurableClient::Codec2ConfigurableClient(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800102 const sp<IConfigurable>& base)
103 : mBase{base},
104 mName{[base]() -> C2String {
105 C2String outName;
106 Return<void> transStatus = base->getName(
107 [&outName](const hidl_string& name) {
108 outName = name.c_str();
109 });
110 return transStatus.isOk() ? outName : "";
111 }()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800112}
113
114c2_status_t Codec2ConfigurableClient::query(
115 const std::vector<C2Param*> &stackParams,
116 const std::vector<C2Param::Index> &heapParamIndices,
117 c2_blocking_t mayBlock,
118 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
119 hidl_vec<ParamIndex> indices(
120 stackParams.size() + heapParamIndices.size());
121 size_t numIndices = 0;
122 for (C2Param* const& stackParam : stackParams) {
123 if (!stackParam) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800124 LOG(WARNING) << "query -- null stack param encountered.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800125 continue;
126 }
127 indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
128 }
129 size_t numStackIndices = numIndices;
130 for (const C2Param::Index& index : heapParamIndices) {
131 indices[numIndices++] =
132 static_cast<ParamIndex>(static_cast<uint32_t>(index));
133 }
134 indices.resize(numIndices);
135 if (heapParams) {
136 heapParams->reserve(heapParams->size() + numIndices);
137 }
138 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800139 Return<void> transStatus = mBase->query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800140 indices,
141 mayBlock == C2_MAY_BLOCK,
142 [&status, &numStackIndices, &stackParams, heapParams](
143 Status s, const Params& p) {
144 status = static_cast<c2_status_t>(s);
145 if (status != C2_OK && status != C2_BAD_INDEX) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800146 LOG(DEBUG) << "query -- call failed: "
147 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800148 return;
149 }
150 std::vector<C2Param*> paramPointers;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800151 if (!parseParamsBlob(&paramPointers, p)) {
152 LOG(ERROR) << "query -- error while parsing params.";
153 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800154 return;
155 }
156 size_t i = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800157 for (auto it = paramPointers.begin();
158 it != paramPointers.end(); ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800159 C2Param* paramPointer = *it;
160 if (numStackIndices > 0) {
161 --numStackIndices;
162 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800163 LOG(WARNING) << "query -- null stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800164 ++it;
165 continue;
166 }
167 for (; i < stackParams.size() && !stackParams[i]; ) {
168 ++i;
169 }
170 if (i >= stackParams.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800171 LOG(ERROR) << "query -- unexpected error.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800172 status = C2_CORRUPTED;
173 return;
174 }
175 if (stackParams[i]->index() != paramPointer->index()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800176 LOG(WARNING) << "query -- param skipped: "
177 "index = "
178 << stackParams[i]->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800179 stackParams[i++]->invalidate();
180 continue;
181 }
182 if (!stackParams[i++]->updateFrom(*paramPointer)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800183 LOG(WARNING) << "query -- param update failed: "
184 "index = "
185 << paramPointer->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800186 }
187 } else {
188 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800189 LOG(WARNING) << "query -- null heap param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800190 ++it;
191 continue;
192 }
193 if (!heapParams) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800194 LOG(WARNING) << "query -- "
195 "unexpected extra stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800196 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800197 heapParams->emplace_back(
198 C2Param::Copy(*paramPointer));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800199 }
200 }
201 ++it;
202 }
203 });
204 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800205 LOG(ERROR) << "query -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800206 return C2_TRANSACTION_FAILED;
207 }
208 return status;
209}
210
211c2_status_t Codec2ConfigurableClient::config(
212 const std::vector<C2Param*> &params,
213 c2_blocking_t mayBlock,
214 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
215 Params hidlParams;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800216 if (!createParamsBlob(&hidlParams, params)) {
217 LOG(ERROR) << "config -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800218 return C2_TRANSACTION_FAILED;
219 }
220 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800221 Return<void> transStatus = mBase->config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800222 hidlParams,
223 mayBlock == C2_MAY_BLOCK,
224 [&status, &params, failures](
225 Status s,
226 const hidl_vec<SettingResult> f,
227 const Params& o) {
228 status = static_cast<c2_status_t>(s);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800229 if (status != C2_OK && status != C2_BAD_INDEX) {
230 LOG(DEBUG) << "config -- call failed: "
231 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800232 }
233 size_t i = failures->size();
234 failures->resize(i + f.size());
235 for (const SettingResult& sf : f) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800236 if (!objcpy(&(*failures)[i++], sf)) {
237 LOG(ERROR) << "config -- "
238 << "invalid SettingResult returned.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800239 return;
240 }
241 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800242 if (!updateParamsFromBlob(params, o)) {
243 LOG(ERROR) << "config -- "
244 << "failed to parse returned params.";
245 status = C2_CORRUPTED;
246 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800247 });
248 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800249 LOG(ERROR) << "config -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800250 return C2_TRANSACTION_FAILED;
251 }
252 return status;
253}
254
255c2_status_t Codec2ConfigurableClient::querySupportedParams(
256 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
257 // TODO: Cache and query properly!
258 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800259 Return<void> transStatus = mBase->querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800260 std::numeric_limits<uint32_t>::min(),
261 std::numeric_limits<uint32_t>::max(),
262 [&status, params](
263 Status s,
264 const hidl_vec<ParamDescriptor>& p) {
265 status = static_cast<c2_status_t>(s);
266 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800267 LOG(DEBUG) << "querySupportedParams -- call failed: "
268 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800269 return;
270 }
271 size_t i = params->size();
272 params->resize(i + p.size());
273 for (const ParamDescriptor& sp : p) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800274 if (!objcpy(&(*params)[i++], sp)) {
275 LOG(ERROR) << "querySupportedParams -- "
276 << "invalid returned ParamDescriptor.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800277 return;
278 }
279 }
280 });
281 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800282 LOG(ERROR) << "querySupportedParams -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800283 return C2_TRANSACTION_FAILED;
284 }
285 return status;
286}
287
288c2_status_t Codec2ConfigurableClient::querySupportedValues(
289 std::vector<C2FieldSupportedValuesQuery>& fields,
290 c2_blocking_t mayBlock) const {
291 hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
292 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800293 if (!objcpy(&inFields[i], fields[i])) {
294 LOG(ERROR) << "querySupportedValues -- bad input";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800295 return C2_TRANSACTION_FAILED;
296 }
297 }
298
299 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800300 Return<void> transStatus = mBase->querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800301 inFields,
302 mayBlock == C2_MAY_BLOCK,
303 [&status, &inFields, &fields](
304 Status s,
305 const hidl_vec<FieldSupportedValuesQueryResult>& r) {
306 status = static_cast<c2_status_t>(s);
307 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800308 LOG(DEBUG) << "querySupportedValues -- call failed: "
309 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800310 return;
311 }
312 if (r.size() != fields.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800313 LOG(ERROR) << "querySupportedValues -- "
314 "input and output lists "
315 "have different sizes.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800316 status = C2_CORRUPTED;
317 return;
318 }
319 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800320 if (!objcpy(&fields[i], inFields[i], r[i])) {
321 LOG(ERROR) << "querySupportedValues -- "
322 "invalid returned value.";
323 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800324 return;
325 }
326 }
327 });
328 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800329 LOG(ERROR) << "querySupportedValues -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800330 return C2_TRANSACTION_FAILED;
331 }
332 return status;
333}
334
335// Codec2Client::Component::HidlListener
336struct Codec2Client::Component::HidlListener : public IComponentListener {
337 std::weak_ptr<Component> component;
338 std::weak_ptr<Listener> base;
339
340 virtual Return<void> onWorkDone(const WorkBundle& workBundle) override {
341 std::list<std::unique_ptr<C2Work>> workItems;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800342 if (!objcpy(&workItems, workBundle)) {
343 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800344 return Void();
345 }
346 // release input buffers potentially held by the component from queue
347 size_t numDiscardedInputBuffers = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800348 std::shared_ptr<Codec2Client::Component> strongComponent =
349 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800350 if (strongComponent) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800351 numDiscardedInputBuffers =
352 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800353 }
354 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800355 listener->onWorkDone(component,
356 workItems,
357 numDiscardedInputBuffers);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800358 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800359 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800360 }
361 return Void();
362 }
363
364 virtual Return<void> onTripped(
365 const hidl_vec<SettingResult>& settingResults) override {
366 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
367 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800368 for (size_t i = 0; i < settingResults.size(); ++i) {
369 std::unique_ptr<C2SettingResult> c2SettingResult;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800370 if (!objcpy(&c2SettingResult, settingResults[i])) {
371 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800372 return Void();
373 }
374 c2SettingResults[i] = std::move(c2SettingResult);
375 }
376 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
377 listener->onTripped(component, c2SettingResults);
378 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800379 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800380 }
381 return Void();
382 }
383
384 virtual Return<void> onError(Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800385 LOG(DEBUG) << "onError --"
386 << " status = " << s
387 << ", errorCode = " << errorCode
388 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800389 if (std::shared_ptr<Listener> listener = base.lock()) {
390 listener->onError(component, s == Status::OK ?
391 errorCode : static_cast<c2_status_t>(s));
392 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800393 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800394 }
395 return Void();
396 }
397
398 virtual Return<void> onFramesRendered(
399 const hidl_vec<RenderedFrame>& renderedFrames) override {
400 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800401 if (!listener) {
402 LOG(DEBUG) << "onFramesRendered -- listener died.";
403 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800404 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800405 for (const RenderedFrame& renderedFrame : renderedFrames) {
406 listener->onFrameRendered(
407 renderedFrame.bufferQueueId,
408 renderedFrame.slotId,
409 renderedFrame.timestampNs);
410 }
411 return Void();
412 }
413
414 virtual Return<void> onInputBuffersReleased(
415 const hidl_vec<InputBuffer>& inputBuffers) override {
416 std::shared_ptr<Listener> listener = base.lock();
417 if (!listener) {
418 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
419 return Void();
420 }
421 std::shared_ptr<Codec2Client::Component> strongComponent =
422 component.lock();
423 if (!strongComponent) {
424 LOG(DEBUG) << "onInputBuffersReleased -- component died.";
425 return Void();
426 }
427 for (const InputBuffer& inputBuffer : inputBuffers) {
428 std::shared_ptr<C2Buffer> buffer =
429 strongComponent->freeInputBuffer(
430 inputBuffer.frameIndex,
431 inputBuffer.arrayIndex);
432 LOG(VERBOSE) << "onInputBuffersReleased --"
433 " received death notification of"
434 " input buffer:"
435 " frameIndex = " << inputBuffer.frameIndex
436 << ", bufferIndex = " << inputBuffer.arrayIndex
437 << ".";
438 if (buffer) {
439 listener->onInputBufferDone(buffer);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800440 }
441 }
442 return Void();
443 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800444
Pawin Vongmasa36653902018-11-15 00:10:25 -0800445};
446
447// Codec2Client
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800448Codec2Client::Codec2Client(const sp<IComponentStore>& base,
449 std::string serviceName)
450 : Configurable{
451 [base]() -> sp<IConfigurable> {
452 Return<sp<IConfigurable>> transResult =
453 base->getConfigurable();
454 return transResult.isOk() ?
455 static_cast<sp<IConfigurable>>(transResult) :
456 nullptr;
457 }()
458 },
459 mBase{base},
460 mListed{false},
461 mServiceName{serviceName} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800462 Return<sp<IClientManager>> transResult = base->getPoolClientManager();
463 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800464 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800465 } else {
466 mHostPoolManager = static_cast<sp<IClientManager>>(transResult);
467 }
468}
469
470c2_status_t Codec2Client::createComponent(
471 const C2String& name,
472 const std::shared_ptr<Codec2Client::Listener>& listener,
473 std::shared_ptr<Codec2Client::Component>* const component) {
474
Pawin Vongmasa36653902018-11-15 00:10:25 -0800475 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800476 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800477 hidlListener->base = listener;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800478 Return<void> transStatus = mBase->createComponent(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800479 name,
480 hidlListener,
481 ClientManager::getInstance(),
482 [&status, component, hidlListener](
483 Status s,
484 const sp<IComponent>& c) {
485 status = static_cast<c2_status_t>(s);
486 if (status != C2_OK) {
487 return;
488 }
489 *component = std::make_shared<Codec2Client::Component>(c);
490 hidlListener->component = *component;
491 });
492 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800493 LOG(ERROR) << "createComponent(" << name.c_str()
494 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800495 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800496 } else if (status != C2_OK) {
497 LOG(ERROR) << "createComponent(" << name.c_str()
498 << ") -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800499 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800500 } else if (!*component) {
501 LOG(ERROR) << "createComponent(" << name.c_str()
502 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800503 return C2_CORRUPTED;
504 }
505
506 status = (*component)->setDeathListener(*component, listener);
507 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800508 LOG(ERROR) << "createComponent(" << name.c_str()
509 << ") -- failed to set up death listener: "
510 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800511 }
512
513 (*component)->mBufferPoolSender.setReceiver(mHostPoolManager);
514 return status;
515}
516
517c2_status_t Codec2Client::createInterface(
518 const C2String& name,
519 std::shared_ptr<Codec2Client::Interface>* const interface) {
520 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800521 Return<void> transStatus = mBase->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800522 name,
523 [&status, interface](
524 Status s,
525 const sp<IComponentInterface>& i) {
526 status = static_cast<c2_status_t>(s);
527 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800528 return;
529 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800530 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800531 });
532 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800533 LOG(ERROR) << "createInterface(" << name.c_str()
534 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800535 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800536 } else if (status != C2_OK) {
537 LOG(ERROR) << "createComponent(" << name.c_str()
538 << ") -- call failed: " << status << ".";
539 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800540 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800541
Pawin Vongmasa36653902018-11-15 00:10:25 -0800542 return status;
543}
544
545c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800546 std::shared_ptr<InputSurface>* const inputSurface) {
547 c2_status_t status;
548 Return<void> transStatus = mBase->createInputSurface(
549 [&status, inputSurface](
550 Status s,
551 const sp<IInputSurface>& i) {
552 status = static_cast<c2_status_t>(s);
553 if (status != C2_OK) {
554 return;
555 }
556 *inputSurface = std::make_shared<InputSurface>(i);
557 });
558 if (!transStatus.isOk()) {
559 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800560 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800561 } else if (status != C2_OK) {
562 LOG(DEBUG) << "createInputSurface -- call failed: "
563 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800564 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800565 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800566}
567
568const std::vector<C2Component::Traits>& Codec2Client::listComponents() const {
569 std::lock_guard<std::mutex> lock(mMutex);
570 if (mListed) {
571 return mTraitsList;
572 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800573 Return<void> transStatus = mBase->listComponents(
574 [this](Status s,
575 const hidl_vec<IComponentStore::ComponentTraits>& t) {
576 if (s != Status::OK) {
577 LOG(DEBUG) << "listComponents -- call failed: "
578 << static_cast<c2_status_t>(s) << ".";
579 return;
580 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800581 mTraitsList.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800582 for (size_t i = 0; i < t.size(); ++i) {
Lajos Molnar8b5c20c2019-01-31 16:15:08 -0800583 if (!objcpy(&mTraitsList[i], t[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800584 LOG(ERROR) << "listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800585 return;
586 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800587 mTraitsList[i].owner = mServiceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800588 }
589 });
590 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800591 LOG(ERROR) << "listComponents -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800592 }
593 mListed = true;
594 return mTraitsList;
595}
596
597c2_status_t Codec2Client::copyBuffer(
598 const std::shared_ptr<C2Buffer>& src,
599 const std::shared_ptr<C2Buffer>& dst) {
600 // TODO: Implement?
601 (void)src;
602 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800603 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800604 return C2_OMITTED;
605}
606
607std::shared_ptr<C2ParamReflector>
608 Codec2Client::getParamReflector() {
609 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
610 // should reflect the HAL API.
611 struct SimpleParamReflector : public C2ParamReflector {
612 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
613 hidl_vec<ParamIndex> indices(1);
614 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
615 std::unique_ptr<C2StructDescriptor> descriptor;
616 Return<void> transStatus = mBase->getStructDescriptors(
617 indices,
618 [&descriptor](
619 Status s,
620 const hidl_vec<StructDescriptor>& sd) {
621 c2_status_t status = static_cast<c2_status_t>(s);
622 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800623 LOG(DEBUG) << "SimpleParamReflector -- "
624 "getStructDescriptors() failed: "
625 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800626 descriptor.reset();
627 return;
628 }
629 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800630 LOG(DEBUG) << "SimpleParamReflector -- "
631 "getStructDescriptors() "
632 "returned vector of size "
633 << sd.size() << ". "
634 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800635 descriptor.reset();
636 return;
637 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800638 if (!objcpy(&descriptor, sd[0])) {
639 LOG(DEBUG) << "SimpleParamReflector -- "
640 "getStructDescriptors() returned "
641 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800642 descriptor.reset();
643 return;
644 }
645 });
646 return descriptor;
647 }
648
649 SimpleParamReflector(sp<Base> base)
650 : mBase(base) { }
651
652 sp<Base> mBase;
653 };
654
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800655 return std::make_shared<SimpleParamReflector>(mBase);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800656};
657
658std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800659 const char* serviceName, bool waitForService) {
660 if (!serviceName) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800661 return nullptr;
662 }
663 sp<Base> baseStore = waitForService ?
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800664 Base::getService(serviceName) :
665 Base::tryGetService(serviceName);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800666 if (!baseStore) {
667 if (waitForService) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800668 LOG(WARNING) << "Codec2.0 service \"" << serviceName << "\""
669 " inaccessible. Check the device manifest.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800670 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800671 LOG(DEBUG) << "Codec2.0 service \"" << serviceName << "\""
672 " unavailable at the moment. "
673 " Wait or check the device manifest.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800674 }
675 return nullptr;
676 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800677 return std::make_shared<Codec2Client>(baseStore, serviceName);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800678}
679
680c2_status_t Codec2Client::ForAllStores(
681 const std::string &key,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800682 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
683 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800684 c2_status_t status = C2_NO_INIT; // no IComponentStores present
685
686 // Cache the mapping key -> index of Codec2Client in getClient().
687 static std::mutex key2IndexMutex;
688 static std::map<std::string, size_t> key2Index;
689
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800690 // By default try all stores. However, try the last known client first. If
691 // the last known client fails, retry once. We do this by pushing the last
692 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800693 std::deque<size_t> indices;
694 for (size_t index = kNumClients; index > 0; ) {
695 indices.push_front(--index);
696 }
697
698 bool wasMapped = false;
699 std::unique_lock<std::mutex> lock(key2IndexMutex);
700 auto it = key2Index.find(key);
701 if (it != key2Index.end()) {
702 indices.push_front(it->second);
703 wasMapped = true;
704 }
705 lock.unlock();
706
707 for (size_t index : indices) {
708 std::shared_ptr<Codec2Client> client = getClient(index);
709 if (client) {
710 status = predicate(client);
711 if (status == C2_OK) {
712 lock.lock();
713 key2Index[key] = index; // update last known client index
714 return status;
715 }
716 }
717 if (wasMapped) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800718 LOG(INFO) << "Could not find \"" << key << "\""
719 " in the last instance. Retrying...";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800720 wasMapped = false;
721 }
722 }
723 return status; // return the last status from a valid client
724}
725
726std::shared_ptr<Codec2Client::Component>
727 Codec2Client::CreateComponentByName(
728 const char* componentName,
729 const std::shared_ptr<Listener>& listener,
730 std::shared_ptr<Codec2Client>* owner) {
731 std::shared_ptr<Component> component;
732 c2_status_t status = ForAllStores(
733 componentName,
734 [owner, &component, componentName, &listener](
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800735 const std::shared_ptr<Codec2Client> &client)
736 -> c2_status_t {
737 c2_status_t status = client->createComponent(componentName,
738 listener,
739 &component);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800740 if (status == C2_OK) {
741 if (owner) {
742 *owner = client;
743 }
744 } else if (status != C2_NOT_FOUND) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800745 LOG(DEBUG) << "IComponentStore("
746 << client->getServiceName()
747 << ")::createComponent(\"" << componentName
748 << "\") returned status = "
749 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800750 }
751 return status;
752 });
753 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800754 LOG(DEBUG) << "Could not create component \"" << componentName << "\". "
755 "Status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800756 }
757 return component;
758}
759
760std::shared_ptr<Codec2Client::Interface>
761 Codec2Client::CreateInterfaceByName(
762 const char* interfaceName,
763 std::shared_ptr<Codec2Client>* owner) {
764 std::shared_ptr<Interface> interface;
765 c2_status_t status = ForAllStores(
766 interfaceName,
767 [owner, &interface, interfaceName](
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800768 const std::shared_ptr<Codec2Client> &client)
769 -> c2_status_t {
770 c2_status_t status = client->createInterface(interfaceName,
771 &interface);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800772 if (status == C2_OK) {
773 if (owner) {
774 *owner = client;
775 }
776 } else if (status != C2_NOT_FOUND) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800777 LOG(DEBUG) << "IComponentStore("
778 << client->getServiceName()
779 << ")::createInterface(\"" << interfaceName
780 << "\") returned status = "
781 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800782 }
783 return status;
784 });
785 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800786 LOG(DEBUG) << "Could not create interface \"" << interfaceName << "\". "
787 "Status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800788 }
789 return interface;
790}
791
792std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface() {
793 uint32_t serviceMask = ::android::base::GetUintProperty(
794 "debug.stagefright.c2inputsurface", uint32_t(0));
795 for (size_t i = 0; i < kNumClients; ++i) {
796 if ((1 << i) & serviceMask) {
797 std::shared_ptr<Codec2Client> client = getClient(i);
798 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
799 if (client &&
800 client->createInputSurface(&inputSurface) == C2_OK &&
801 inputSurface) {
802 return inputSurface;
803 }
804 }
805 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800806 LOG(INFO) << "Could not create an input surface "
807 "from any Codec2.0 services.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800808 return nullptr;
809}
810
811const std::vector<C2Component::Traits>& Codec2Client::ListComponents() {
812 static std::vector<C2Component::Traits> traitsList = [](){
813 std::vector<C2Component::Traits> list;
814 size_t listSize = 0;
815 ClientList clientList = getClientList();
816 for (const std::shared_ptr<Codec2Client>& client : clientList) {
817 if (!client) {
818 continue;
819 }
820 listSize += client->listComponents().size();
821 }
822 list.reserve(listSize);
823 for (const std::shared_ptr<Codec2Client>& client : clientList) {
824 if (!client) {
825 continue;
826 }
827 list.insert(
828 list.end(),
829 client->listComponents().begin(),
830 client->listComponents().end());
831 }
832 return list;
833 }();
834
835 return traitsList;
836}
837
838// Codec2Client::Listener
839
840Codec2Client::Listener::~Listener() {
841}
842
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800843// Codec2Client::Interface
844Codec2Client::Interface::Interface(const sp<Base>& base)
845 : Configurable{
846 [base]() -> sp<IConfigurable> {
847 Return<sp<IConfigurable>> transResult =
848 base->getConfigurable();
849 return transResult.isOk() ?
850 static_cast<sp<IConfigurable>>(transResult) :
851 nullptr;
852 }()
853 },
854 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800855}
856
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800857// Codec2Client::Component
858Codec2Client::Component::Component(const sp<Base>& base)
859 : Configurable{
860 [base]() -> sp<IConfigurable> {
861 Return<sp<IComponentInterface>> transResult1 =
862 base->getInterface();
863 if (!transResult1.isOk()) {
864 return nullptr;
865 }
866 Return<sp<IConfigurable>> transResult2 =
867 static_cast<sp<IComponentInterface>>(transResult1)->
868 getConfigurable();
869 return transResult2.isOk() ?
870 static_cast<sp<IConfigurable>>(transResult2) :
871 nullptr;
872 }()
873 },
874 mBase{base},
875 mBufferPoolSender{nullptr} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800876}
877
878Codec2Client::Component::~Component() {
879}
880
881c2_status_t Codec2Client::Component::createBlockPool(
882 C2Allocator::id_t id,
883 C2BlockPool::local_id_t* blockPoolId,
884 std::shared_ptr<Codec2Client::Configurable>* configurable) {
885 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800886 Return<void> transStatus = mBase->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800887 static_cast<uint32_t>(id),
888 [&status, blockPoolId, configurable](
889 Status s,
890 uint64_t pId,
891 const sp<IConfigurable>& c) {
892 status = static_cast<c2_status_t>(s);
893 configurable->reset();
894 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800895 LOG(DEBUG) << "createBlockPool -- call failed: "
896 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800897 return;
898 }
899 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800900 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800901 });
902 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800903 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800904 return C2_TRANSACTION_FAILED;
905 }
906 return status;
907}
908
909c2_status_t Codec2Client::Component::destroyBlockPool(
910 C2BlockPool::local_id_t localId) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800911 Return<Status> transResult = mBase->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800912 static_cast<uint64_t>(localId));
913 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800914 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800915 return C2_TRANSACTION_FAILED;
916 }
917 return static_cast<c2_status_t>(static_cast<Status>(transResult));
918}
919
920size_t Codec2Client::Component::handleOnWorkDone(
921 const std::list<std::unique_ptr<C2Work>> &workItems) {
922 // Input buffers' lifetime management
923 std::vector<uint64_t> inputDone;
924 for (const std::unique_ptr<C2Work> &work : workItems) {
925 if (work) {
926 if (work->worklets.empty()
927 || !work->worklets.back()
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800928 || (work->worklets.back()->output.flags &
929 C2FrameData::FLAG_INCOMPLETE) == 0) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800930 // input is complete
931 inputDone.emplace_back(work->input.ordinal.frameIndex.peeku());
932 }
933 }
934 }
935
936 size_t numDiscardedInputBuffers = 0;
937 {
938 std::lock_guard<std::mutex> lock(mInputBuffersMutex);
939 for (uint64_t inputIndex : inputDone) {
940 auto it = mInputBuffers.find(inputIndex);
941 if (it == mInputBuffers.end()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800942 LOG(VERBOSE) << "onWorkDone -- returned consumed/unknown "
943 "input frame: index = "
944 << inputIndex << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800945 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800946 LOG(VERBOSE) << "onWorkDone -- processed input frame: "
947 << inputIndex
948 << " (containing " << it->second.size()
949 << " buffers).";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800950 mInputBuffers.erase(it);
951 mInputBufferCount.erase(inputIndex);
952 ++numDiscardedInputBuffers;
953 }
954 }
955 }
956
957 // Output bufferqueue-based blocks' lifetime management
958 mOutputBufferQueueMutex.lock();
959 sp<IGraphicBufferProducer> igbp = mOutputIgbp;
960 uint64_t bqId = mOutputBqId;
961 uint32_t generation = mOutputGeneration;
962 mOutputBufferQueueMutex.unlock();
963
964 if (igbp) {
965 holdBufferQueueBlocks(workItems, igbp, bqId, generation);
966 }
967 return numDiscardedInputBuffers;
968}
969
970std::shared_ptr<C2Buffer> Codec2Client::Component::freeInputBuffer(
971 uint64_t frameIndex,
972 size_t bufferIndex) {
973 std::shared_ptr<C2Buffer> buffer;
974 std::lock_guard<std::mutex> lock(mInputBuffersMutex);
975 auto it = mInputBuffers.find(frameIndex);
976 if (it == mInputBuffers.end()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800977 LOG(INFO) << "freeInputBuffer -- Unrecognized input frame index "
978 << frameIndex << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800979 return nullptr;
980 }
981 if (bufferIndex >= it->second.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800982 LOG(INFO) << "freeInputBuffer -- Input buffer number " << bufferIndex
983 << " is not valid in input with frame index " << frameIndex
984 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800985 return nullptr;
986 }
987 buffer = it->second[bufferIndex];
988 if (!buffer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800989 LOG(INFO) << "freeInputBuffer -- Input buffer number " << bufferIndex
990 << " in input with frame index " << frameIndex
991 << " has already been freed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800992 return nullptr;
993 }
994 it->second[bufferIndex] = nullptr;
995 if (--mInputBufferCount[frameIndex] == 0) {
996 mInputBuffers.erase(it);
997 mInputBufferCount.erase(frameIndex);
998 }
999 return buffer;
1000}
1001
1002c2_status_t Codec2Client::Component::queue(
1003 std::list<std::unique_ptr<C2Work>>* const items) {
1004 // remember input buffers queued to hold reference to them
1005 {
1006 std::lock_guard<std::mutex> lock(mInputBuffersMutex);
1007 for (const std::unique_ptr<C2Work> &work : *items) {
1008 if (!work) {
1009 continue;
1010 }
1011 if (work->input.buffers.size() == 0) {
1012 continue;
1013 }
1014
1015 uint64_t inputIndex = work->input.ordinal.frameIndex.peeku();
1016 auto res = mInputBuffers.emplace(inputIndex, work->input.buffers);
1017 if (!res.second) {
1018 // TODO: append? - for now we are replacing
1019 res.first->second = work->input.buffers;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001020 LOG(INFO) << "queue -- duplicate input frame index: "
1021 << inputIndex
1022 << ". Discarding the old input frame...";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001023 }
1024 mInputBufferCount[inputIndex] = work->input.buffers.size();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001025 LOG(VERBOSE) << "queue -- queuing input frame: "
1026 << "index = " << inputIndex
1027 << ", number of buffers = "
1028 << work->input.buffers.size()
1029 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001030 }
1031 }
1032
1033 WorkBundle workBundle;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001034 if (!objcpy(&workBundle, *items, &mBufferPoolSender)) {
1035 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001036 return C2_TRANSACTION_FAILED;
1037 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001038 Return<Status> transStatus = mBase->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001039 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001040 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001041 return C2_TRANSACTION_FAILED;
1042 }
1043 c2_status_t status =
1044 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1045 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001046 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001047 }
1048 return status;
1049}
1050
1051c2_status_t Codec2Client::Component::flush(
1052 C2Component::flush_mode_t mode,
1053 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
1054 (void)mode; // Flush mode isn't supported in HIDL yet.
1055 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001056 Return<void> transStatus = mBase->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001057 [&status, flushedWork](
1058 Status s, const WorkBundle& wb) {
1059 status = static_cast<c2_status_t>(s);
1060 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001061 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001062 return;
1063 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001064 if (!objcpy(flushedWork, wb)) {
1065 status = C2_CORRUPTED;
1066 } else {
1067 status = C2_OK;
1068 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001069 });
1070 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001071 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001072 return C2_TRANSACTION_FAILED;
1073 }
1074
1075 // Indices of flushed work items.
1076 std::vector<uint64_t> flushedIndices;
1077 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
1078 if (work) {
1079 if (work->worklets.empty()
1080 || !work->worklets.back()
1081 || (work->worklets.back()->output.flags &
1082 C2FrameData::FLAG_INCOMPLETE) == 0) {
1083 // input is complete
1084 flushedIndices.emplace_back(
1085 work->input.ordinal.frameIndex.peeku());
1086 }
1087 }
1088 }
1089
1090 // Input buffers' lifetime management
1091 for (uint64_t flushedIndex : flushedIndices) {
1092 std::lock_guard<std::mutex> lock(mInputBuffersMutex);
1093 auto it = mInputBuffers.find(flushedIndex);
1094 if (it == mInputBuffers.end()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001095 LOG(VERBOSE) << "flush -- returned consumed/unknown input frame: "
1096 "index = " << flushedIndex << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001097 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001098 LOG(VERBOSE) << "flush -- returned unprocessed input frame: "
1099 "index = " << flushedIndex
1100 << ", number of buffers = "
1101 << mInputBufferCount[flushedIndex]
1102 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001103 mInputBuffers.erase(it);
1104 mInputBufferCount.erase(flushedIndex);
1105 }
1106 }
1107
1108 // Output bufferqueue-based blocks' lifetime management
1109 mOutputBufferQueueMutex.lock();
1110 sp<IGraphicBufferProducer> igbp = mOutputIgbp;
1111 uint64_t bqId = mOutputBqId;
1112 uint32_t generation = mOutputGeneration;
1113 mOutputBufferQueueMutex.unlock();
1114
1115 if (igbp) {
1116 holdBufferQueueBlocks(*flushedWork, igbp, bqId, generation);
1117 }
1118
1119 return status;
1120}
1121
1122c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001123 Return<Status> transStatus = mBase->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001124 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1125 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001126 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001127 return C2_TRANSACTION_FAILED;
1128 }
1129 c2_status_t status =
1130 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1131 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001132 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001133 }
1134 return status;
1135}
1136
1137c2_status_t Codec2Client::Component::start() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001138 Return<Status> transStatus = mBase->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001139 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001140 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001141 return C2_TRANSACTION_FAILED;
1142 }
1143 c2_status_t status =
1144 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1145 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001146 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001147 }
1148 return status;
1149}
1150
1151c2_status_t Codec2Client::Component::stop() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001152 Return<Status> transStatus = mBase->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001153 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001154 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001155 return C2_TRANSACTION_FAILED;
1156 }
1157 c2_status_t status =
1158 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1159 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001160 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001161 }
1162 mInputBuffersMutex.lock();
1163 mInputBuffers.clear();
1164 mInputBufferCount.clear();
1165 mInputBuffersMutex.unlock();
1166 return status;
1167}
1168
1169c2_status_t Codec2Client::Component::reset() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001170 Return<Status> transStatus = mBase->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001171 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001172 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001173 return C2_TRANSACTION_FAILED;
1174 }
1175 c2_status_t status =
1176 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1177 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001178 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001179 }
1180 mInputBuffersMutex.lock();
1181 mInputBuffers.clear();
1182 mInputBufferCount.clear();
1183 mInputBuffersMutex.unlock();
1184 return status;
1185}
1186
1187c2_status_t Codec2Client::Component::release() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001188 Return<Status> transStatus = mBase->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001189 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001190 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001191 return C2_TRANSACTION_FAILED;
1192 }
1193 c2_status_t status =
1194 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1195 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001196 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001197 }
1198 mInputBuffersMutex.lock();
1199 mInputBuffers.clear();
1200 mInputBufferCount.clear();
1201 mInputBuffersMutex.unlock();
1202 return status;
1203}
1204
1205c2_status_t Codec2Client::Component::setOutputSurface(
1206 C2BlockPool::local_id_t blockPoolId,
1207 const sp<IGraphicBufferProducer>& surface,
1208 uint32_t generation) {
1209 sp<HGraphicBufferProducer> igbp = surface->getHalInterface();
1210 if (!igbp) {
1211 igbp = new TWGraphicBufferProducer<HGraphicBufferProducer>(surface);
1212 }
1213
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001214 Return<Status> transStatus = mBase->setOutputSurface(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001215 static_cast<uint64_t>(blockPoolId), igbp);
1216 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001217 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001218 return C2_TRANSACTION_FAILED;
1219 }
1220 c2_status_t status =
1221 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1222 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001223 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001224 } else {
1225 std::lock_guard<std::mutex> lock(mOutputBufferQueueMutex);
1226 if (mOutputIgbp != surface) {
1227 mOutputIgbp = surface;
1228 if (!surface) {
1229 mOutputBqId = 0;
1230 } else if (surface->getUniqueId(&mOutputBqId) != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001231 LOG(ERROR) << "setOutputSurface -- "
1232 "cannot obtain bufferqueue id.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001233 }
1234 }
1235 mOutputGeneration = generation;
1236 }
1237 return status;
1238}
1239
1240status_t Codec2Client::Component::queueToOutputSurface(
1241 const C2ConstGraphicBlock& block,
1242 const QueueBufferInput& input,
1243 QueueBufferOutput* output) {
1244 uint32_t generation;
1245 uint64_t bqId;
1246 int32_t bqSlot;
1247 if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot) ||
1248 bqId == 0) {
1249 // Block not from bufferqueue -- it must be attached before queuing.
1250
1251 mOutputBufferQueueMutex.lock();
1252 sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp;
1253 uint32_t outputGeneration = mOutputGeneration;
1254 mOutputBufferQueueMutex.unlock();
1255
Sungtak Lee9b148812019-01-27 16:30:13 -08001256 status_t status = attachToBufferQueue(block,
Pawin Vongmasa36653902018-11-15 00:10:25 -08001257 outputIgbp,
1258 outputGeneration,
1259 &bqSlot);
1260 if (status != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001261 LOG(WARNING) << "queueToOutputSurface -- attaching failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001262 return INVALID_OPERATION;
1263 }
1264
1265 status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
1266 input, output);
1267 if (status != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001268 LOG(ERROR) << "queueToOutputSurface -- queueBuffer() failed "
1269 "on non-bufferqueue-based block. "
1270 "Error = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001271 return status;
1272 }
1273 return OK;
1274 }
1275
1276 mOutputBufferQueueMutex.lock();
1277 sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp;
1278 uint64_t outputBqId = mOutputBqId;
1279 uint32_t outputGeneration = mOutputGeneration;
1280 mOutputBufferQueueMutex.unlock();
1281
1282 if (!outputIgbp) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001283 LOG(VERBOSE) << "queueToOutputSurface -- output surface is null.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001284 return NO_INIT;
1285 }
1286
Sungtak Lee9b148812019-01-27 16:30:13 -08001287 if (bqId != outputBqId || generation != outputGeneration) {
1288 if (!holdBufferQueueBlock(block, mOutputIgbp, mOutputBqId, mOutputGeneration)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001289 LOG(ERROR) << "queueToOutputSurface -- migration failed.";
Sungtak Lee9b148812019-01-27 16:30:13 -08001290 return DEAD_OBJECT;
1291 }
1292 if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001293 LOG(ERROR) << "queueToOutputSurface -- corrupted bufferqueue assignment.";
Sungtak Lee9b148812019-01-27 16:30:13 -08001294 return UNKNOWN_ERROR;
1295 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001296 }
1297
1298 status_t status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
1299 input, output);
1300 if (status != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001301 LOG(DEBUG) << "queueToOutputSurface -- queueBuffer() failed "
1302 "on bufferqueue-based block. "
1303 "Error = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001304 return status;
1305 }
1306 if (!yieldBufferQueueBlock(block)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001307 LOG(DEBUG) << "queueToOutputSurface -- cannot yield "
1308 "bufferqueue-based block to the bufferqueue.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001309 return UNKNOWN_ERROR;
1310 }
1311 return OK;
1312}
1313
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001314c2_status_t Codec2Client::Component::connectToInputSurface(
1315 const std::shared_ptr<InputSurface>& inputSurface,
1316 std::shared_ptr<InputSurfaceConnection>* connection) {
1317 c2_status_t status;
1318 Return<void> transStatus = mBase->connectToInputSurface(
1319 inputSurface->mBase,
1320 [&status, connection](
1321 Status s, const sp<IInputSurfaceConnection>& c) {
1322 status = static_cast<c2_status_t>(s);
1323 if (status != C2_OK) {
1324 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1325 << status << ".";
1326 return;
1327 }
1328 *connection = std::make_shared<InputSurfaceConnection>(c);
1329 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001330 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001331 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001332 return C2_TRANSACTION_FAILED;
1333 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001334 return status;
1335}
1336
1337c2_status_t Codec2Client::Component::connectToOmxInputSurface(
1338 const sp<HGraphicBufferProducer>& producer,
1339 const sp<HGraphicBufferSource>& source,
1340 std::shared_ptr<InputSurfaceConnection>* connection) {
1341 c2_status_t status;
1342 Return<void> transStatus = mBase->connectToOmxInputSurface(
1343 producer, source,
1344 [&status, connection](
1345 Status s, const sp<IInputSurfaceConnection>& c) {
1346 status = static_cast<c2_status_t>(s);
1347 if (status != C2_OK) {
1348 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1349 << status << ".";
1350 return;
1351 }
1352 *connection = std::make_shared<InputSurfaceConnection>(c);
1353 });
1354 if (!transStatus.isOk()) {
1355 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1356 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001357 }
1358 return status;
1359}
1360
1361c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001362 Return<Status> transStatus = mBase->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001363 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001364 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001365 return C2_TRANSACTION_FAILED;
1366 }
1367 c2_status_t status =
1368 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1369 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001370 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1371 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001372 }
1373 return status;
1374}
1375
1376c2_status_t Codec2Client::Component::setDeathListener(
1377 const std::shared_ptr<Component>& component,
1378 const std::shared_ptr<Listener>& listener) {
1379
1380 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1381 std::weak_ptr<Component> component;
1382 std::weak_ptr<Listener> base;
1383
1384 virtual void serviceDied(
1385 uint64_t /* cookie */,
1386 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1387 ) override {
1388 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1389 listener->onDeath(component);
1390 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001391 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001392 }
1393 }
1394 };
1395
1396 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1397 deathRecipient->base = listener;
1398 deathRecipient->component = component;
1399
1400 component->mDeathRecipient = deathRecipient;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001401 Return<bool> transResult = component->mBase->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001402 component->mDeathRecipient, 0);
1403 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001404 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001405 return C2_TRANSACTION_FAILED;
1406 }
1407 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001408 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001409 return C2_CORRUPTED;
1410 }
1411 return C2_OK;
1412}
1413
1414// Codec2Client::InputSurface
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001415Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base)
1416 : Configurable{
1417 [base]() -> sp<IConfigurable> {
1418 Return<sp<IConfigurable>> transResult =
1419 base->getConfigurable();
1420 return transResult.isOk() ?
1421 static_cast<sp<IConfigurable>>(transResult) :
1422 nullptr;
1423 }()
1424 },
1425 mBase{base},
1426 mGraphicBufferProducer{new
Pawin Vongmasa36653902018-11-15 00:10:25 -08001427 ::android::hardware::graphics::bufferqueue::V1_0::utils::
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001428 H2BGraphicBufferProducer([base]() -> sp<HGraphicBufferProducer> {
1429 Return<sp<HGraphicBufferProducer>> transResult =
1430 base->getGraphicBufferProducer();
1431 return transResult.isOk() ?
1432 static_cast<sp<HGraphicBufferProducer>>(transResult) :
1433 nullptr;
1434 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001435}
1436
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001437sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08001438 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1439 return mGraphicBufferProducer;
1440}
1441
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001442sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001443 return mBase;
1444}
1445
1446// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08001447Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001448 const sp<IInputSurfaceConnection>& base)
1449 : Configurable{
1450 [base]() -> sp<IConfigurable> {
1451 Return<sp<IConfigurable>> transResult =
1452 base->getConfigurable();
1453 return transResult.isOk() ?
1454 static_cast<sp<IConfigurable>>(transResult) :
1455 nullptr;
1456 }()
1457 },
1458 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001459}
1460
1461c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001462 Return<Status> transResult = mBase->disconnect();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001463 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1464}
1465
1466} // namespace android
1467