blob: 5b52fcd5e831b5c1dda20bdaa25b725fcb18e909 [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());
582 mAliasesBuffer.resize(t.size());
583 for (size_t i = 0; i < t.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800584 if (!objcpy(&mTraitsList[i], &mAliasesBuffer[i], t[i])) {
585 LOG(ERROR) << "listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800586 return;
587 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800588 mTraitsList[i].owner = mServiceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800589 }
590 });
591 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800592 LOG(ERROR) << "listComponents -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800593 }
594 mListed = true;
595 return mTraitsList;
596}
597
598c2_status_t Codec2Client::copyBuffer(
599 const std::shared_ptr<C2Buffer>& src,
600 const std::shared_ptr<C2Buffer>& dst) {
601 // TODO: Implement?
602 (void)src;
603 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800604 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800605 return C2_OMITTED;
606}
607
608std::shared_ptr<C2ParamReflector>
609 Codec2Client::getParamReflector() {
610 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
611 // should reflect the HAL API.
612 struct SimpleParamReflector : public C2ParamReflector {
613 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
614 hidl_vec<ParamIndex> indices(1);
615 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
616 std::unique_ptr<C2StructDescriptor> descriptor;
617 Return<void> transStatus = mBase->getStructDescriptors(
618 indices,
619 [&descriptor](
620 Status s,
621 const hidl_vec<StructDescriptor>& sd) {
622 c2_status_t status = static_cast<c2_status_t>(s);
623 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800624 LOG(DEBUG) << "SimpleParamReflector -- "
625 "getStructDescriptors() failed: "
626 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800627 descriptor.reset();
628 return;
629 }
630 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800631 LOG(DEBUG) << "SimpleParamReflector -- "
632 "getStructDescriptors() "
633 "returned vector of size "
634 << sd.size() << ". "
635 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800636 descriptor.reset();
637 return;
638 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800639 if (!objcpy(&descriptor, sd[0])) {
640 LOG(DEBUG) << "SimpleParamReflector -- "
641 "getStructDescriptors() returned "
642 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800643 descriptor.reset();
644 return;
645 }
646 });
647 return descriptor;
648 }
649
650 SimpleParamReflector(sp<Base> base)
651 : mBase(base) { }
652
653 sp<Base> mBase;
654 };
655
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800656 return std::make_shared<SimpleParamReflector>(mBase);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800657};
658
659std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800660 const char* serviceName, bool waitForService) {
661 if (!serviceName) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800662 return nullptr;
663 }
664 sp<Base> baseStore = waitForService ?
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800665 Base::getService(serviceName) :
666 Base::tryGetService(serviceName);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800667 if (!baseStore) {
668 if (waitForService) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800669 LOG(WARNING) << "Codec2.0 service \"" << serviceName << "\""
670 " inaccessible. Check the device manifest.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800671 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800672 LOG(DEBUG) << "Codec2.0 service \"" << serviceName << "\""
673 " unavailable at the moment. "
674 " Wait or check the device manifest.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800675 }
676 return nullptr;
677 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800678 return std::make_shared<Codec2Client>(baseStore, serviceName);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800679}
680
681c2_status_t Codec2Client::ForAllStores(
682 const std::string &key,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800683 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
684 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800685 c2_status_t status = C2_NO_INIT; // no IComponentStores present
686
687 // Cache the mapping key -> index of Codec2Client in getClient().
688 static std::mutex key2IndexMutex;
689 static std::map<std::string, size_t> key2Index;
690
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800691 // By default try all stores. However, try the last known client first. If
692 // the last known client fails, retry once. We do this by pushing the last
693 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800694 std::deque<size_t> indices;
695 for (size_t index = kNumClients; index > 0; ) {
696 indices.push_front(--index);
697 }
698
699 bool wasMapped = false;
700 std::unique_lock<std::mutex> lock(key2IndexMutex);
701 auto it = key2Index.find(key);
702 if (it != key2Index.end()) {
703 indices.push_front(it->second);
704 wasMapped = true;
705 }
706 lock.unlock();
707
708 for (size_t index : indices) {
709 std::shared_ptr<Codec2Client> client = getClient(index);
710 if (client) {
711 status = predicate(client);
712 if (status == C2_OK) {
713 lock.lock();
714 key2Index[key] = index; // update last known client index
715 return status;
716 }
717 }
718 if (wasMapped) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800719 LOG(INFO) << "Could not find \"" << key << "\""
720 " in the last instance. Retrying...";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800721 wasMapped = false;
722 }
723 }
724 return status; // return the last status from a valid client
725}
726
727std::shared_ptr<Codec2Client::Component>
728 Codec2Client::CreateComponentByName(
729 const char* componentName,
730 const std::shared_ptr<Listener>& listener,
731 std::shared_ptr<Codec2Client>* owner) {
732 std::shared_ptr<Component> component;
733 c2_status_t status = ForAllStores(
734 componentName,
735 [owner, &component, componentName, &listener](
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800736 const std::shared_ptr<Codec2Client> &client)
737 -> c2_status_t {
738 c2_status_t status = client->createComponent(componentName,
739 listener,
740 &component);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800741 if (status == C2_OK) {
742 if (owner) {
743 *owner = client;
744 }
745 } else if (status != C2_NOT_FOUND) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800746 LOG(DEBUG) << "IComponentStore("
747 << client->getServiceName()
748 << ")::createComponent(\"" << componentName
749 << "\") returned status = "
750 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800751 }
752 return status;
753 });
754 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800755 LOG(DEBUG) << "Could not create component \"" << componentName << "\". "
756 "Status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800757 }
758 return component;
759}
760
761std::shared_ptr<Codec2Client::Interface>
762 Codec2Client::CreateInterfaceByName(
763 const char* interfaceName,
764 std::shared_ptr<Codec2Client>* owner) {
765 std::shared_ptr<Interface> interface;
766 c2_status_t status = ForAllStores(
767 interfaceName,
768 [owner, &interface, interfaceName](
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800769 const std::shared_ptr<Codec2Client> &client)
770 -> c2_status_t {
771 c2_status_t status = client->createInterface(interfaceName,
772 &interface);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800773 if (status == C2_OK) {
774 if (owner) {
775 *owner = client;
776 }
777 } else if (status != C2_NOT_FOUND) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800778 LOG(DEBUG) << "IComponentStore("
779 << client->getServiceName()
780 << ")::createInterface(\"" << interfaceName
781 << "\") returned status = "
782 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800783 }
784 return status;
785 });
786 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800787 LOG(DEBUG) << "Could not create interface \"" << interfaceName << "\". "
788 "Status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800789 }
790 return interface;
791}
792
793std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface() {
794 uint32_t serviceMask = ::android::base::GetUintProperty(
795 "debug.stagefright.c2inputsurface", uint32_t(0));
796 for (size_t i = 0; i < kNumClients; ++i) {
797 if ((1 << i) & serviceMask) {
798 std::shared_ptr<Codec2Client> client = getClient(i);
799 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
800 if (client &&
801 client->createInputSurface(&inputSurface) == C2_OK &&
802 inputSurface) {
803 return inputSurface;
804 }
805 }
806 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800807 LOG(INFO) << "Could not create an input surface "
808 "from any Codec2.0 services.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800809 return nullptr;
810}
811
812const std::vector<C2Component::Traits>& Codec2Client::ListComponents() {
813 static std::vector<C2Component::Traits> traitsList = [](){
814 std::vector<C2Component::Traits> list;
815 size_t listSize = 0;
816 ClientList clientList = getClientList();
817 for (const std::shared_ptr<Codec2Client>& client : clientList) {
818 if (!client) {
819 continue;
820 }
821 listSize += client->listComponents().size();
822 }
823 list.reserve(listSize);
824 for (const std::shared_ptr<Codec2Client>& client : clientList) {
825 if (!client) {
826 continue;
827 }
828 list.insert(
829 list.end(),
830 client->listComponents().begin(),
831 client->listComponents().end());
832 }
833 return list;
834 }();
835
836 return traitsList;
837}
838
839// Codec2Client::Listener
840
841Codec2Client::Listener::~Listener() {
842}
843
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800844// Codec2Client::Interface
845Codec2Client::Interface::Interface(const sp<Base>& base)
846 : Configurable{
847 [base]() -> sp<IConfigurable> {
848 Return<sp<IConfigurable>> transResult =
849 base->getConfigurable();
850 return transResult.isOk() ?
851 static_cast<sp<IConfigurable>>(transResult) :
852 nullptr;
853 }()
854 },
855 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800856}
857
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800858// Codec2Client::Component
859Codec2Client::Component::Component(const sp<Base>& base)
860 : Configurable{
861 [base]() -> sp<IConfigurable> {
862 Return<sp<IComponentInterface>> transResult1 =
863 base->getInterface();
864 if (!transResult1.isOk()) {
865 return nullptr;
866 }
867 Return<sp<IConfigurable>> transResult2 =
868 static_cast<sp<IComponentInterface>>(transResult1)->
869 getConfigurable();
870 return transResult2.isOk() ?
871 static_cast<sp<IConfigurable>>(transResult2) :
872 nullptr;
873 }()
874 },
875 mBase{base},
876 mBufferPoolSender{nullptr} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800877}
878
879Codec2Client::Component::~Component() {
880}
881
882c2_status_t Codec2Client::Component::createBlockPool(
883 C2Allocator::id_t id,
884 C2BlockPool::local_id_t* blockPoolId,
885 std::shared_ptr<Codec2Client::Configurable>* configurable) {
886 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800887 Return<void> transStatus = mBase->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800888 static_cast<uint32_t>(id),
889 [&status, blockPoolId, configurable](
890 Status s,
891 uint64_t pId,
892 const sp<IConfigurable>& c) {
893 status = static_cast<c2_status_t>(s);
894 configurable->reset();
895 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800896 LOG(DEBUG) << "createBlockPool -- call failed: "
897 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800898 return;
899 }
900 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800901 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800902 });
903 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800904 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800905 return C2_TRANSACTION_FAILED;
906 }
907 return status;
908}
909
910c2_status_t Codec2Client::Component::destroyBlockPool(
911 C2BlockPool::local_id_t localId) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800912 Return<Status> transResult = mBase->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800913 static_cast<uint64_t>(localId));
914 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800915 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800916 return C2_TRANSACTION_FAILED;
917 }
918 return static_cast<c2_status_t>(static_cast<Status>(transResult));
919}
920
921size_t Codec2Client::Component::handleOnWorkDone(
922 const std::list<std::unique_ptr<C2Work>> &workItems) {
923 // Input buffers' lifetime management
924 std::vector<uint64_t> inputDone;
925 for (const std::unique_ptr<C2Work> &work : workItems) {
926 if (work) {
927 if (work->worklets.empty()
928 || !work->worklets.back()
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800929 || (work->worklets.back()->output.flags &
930 C2FrameData::FLAG_INCOMPLETE) == 0) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800931 // input is complete
932 inputDone.emplace_back(work->input.ordinal.frameIndex.peeku());
933 }
934 }
935 }
936
937 size_t numDiscardedInputBuffers = 0;
938 {
939 std::lock_guard<std::mutex> lock(mInputBuffersMutex);
940 for (uint64_t inputIndex : inputDone) {
941 auto it = mInputBuffers.find(inputIndex);
942 if (it == mInputBuffers.end()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800943 LOG(VERBOSE) << "onWorkDone -- returned consumed/unknown "
944 "input frame: index = "
945 << inputIndex << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800946 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800947 LOG(VERBOSE) << "onWorkDone -- processed input frame: "
948 << inputIndex
949 << " (containing " << it->second.size()
950 << " buffers).";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800951 mInputBuffers.erase(it);
952 mInputBufferCount.erase(inputIndex);
953 ++numDiscardedInputBuffers;
954 }
955 }
956 }
957
958 // Output bufferqueue-based blocks' lifetime management
959 mOutputBufferQueueMutex.lock();
960 sp<IGraphicBufferProducer> igbp = mOutputIgbp;
961 uint64_t bqId = mOutputBqId;
962 uint32_t generation = mOutputGeneration;
963 mOutputBufferQueueMutex.unlock();
964
965 if (igbp) {
966 holdBufferQueueBlocks(workItems, igbp, bqId, generation);
967 }
968 return numDiscardedInputBuffers;
969}
970
971std::shared_ptr<C2Buffer> Codec2Client::Component::freeInputBuffer(
972 uint64_t frameIndex,
973 size_t bufferIndex) {
974 std::shared_ptr<C2Buffer> buffer;
975 std::lock_guard<std::mutex> lock(mInputBuffersMutex);
976 auto it = mInputBuffers.find(frameIndex);
977 if (it == mInputBuffers.end()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800978 LOG(INFO) << "freeInputBuffer -- Unrecognized input frame index "
979 << frameIndex << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800980 return nullptr;
981 }
982 if (bufferIndex >= it->second.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800983 LOG(INFO) << "freeInputBuffer -- Input buffer number " << bufferIndex
984 << " is not valid in input with frame index " << frameIndex
985 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800986 return nullptr;
987 }
988 buffer = it->second[bufferIndex];
989 if (!buffer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800990 LOG(INFO) << "freeInputBuffer -- Input buffer number " << bufferIndex
991 << " in input with frame index " << frameIndex
992 << " has already been freed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800993 return nullptr;
994 }
995 it->second[bufferIndex] = nullptr;
996 if (--mInputBufferCount[frameIndex] == 0) {
997 mInputBuffers.erase(it);
998 mInputBufferCount.erase(frameIndex);
999 }
1000 return buffer;
1001}
1002
1003c2_status_t Codec2Client::Component::queue(
1004 std::list<std::unique_ptr<C2Work>>* const items) {
1005 // remember input buffers queued to hold reference to them
1006 {
1007 std::lock_guard<std::mutex> lock(mInputBuffersMutex);
1008 for (const std::unique_ptr<C2Work> &work : *items) {
1009 if (!work) {
1010 continue;
1011 }
1012 if (work->input.buffers.size() == 0) {
1013 continue;
1014 }
1015
1016 uint64_t inputIndex = work->input.ordinal.frameIndex.peeku();
1017 auto res = mInputBuffers.emplace(inputIndex, work->input.buffers);
1018 if (!res.second) {
1019 // TODO: append? - for now we are replacing
1020 res.first->second = work->input.buffers;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001021 LOG(INFO) << "queue -- duplicate input frame index: "
1022 << inputIndex
1023 << ". Discarding the old input frame...";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001024 }
1025 mInputBufferCount[inputIndex] = work->input.buffers.size();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001026 LOG(VERBOSE) << "queue -- queuing input frame: "
1027 << "index = " << inputIndex
1028 << ", number of buffers = "
1029 << work->input.buffers.size()
1030 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001031 }
1032 }
1033
1034 WorkBundle workBundle;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001035 if (!objcpy(&workBundle, *items, &mBufferPoolSender)) {
1036 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001037 return C2_TRANSACTION_FAILED;
1038 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001039 Return<Status> transStatus = mBase->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001040 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001041 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001042 return C2_TRANSACTION_FAILED;
1043 }
1044 c2_status_t status =
1045 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1046 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001047 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001048 }
1049 return status;
1050}
1051
1052c2_status_t Codec2Client::Component::flush(
1053 C2Component::flush_mode_t mode,
1054 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
1055 (void)mode; // Flush mode isn't supported in HIDL yet.
1056 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001057 Return<void> transStatus = mBase->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001058 [&status, flushedWork](
1059 Status s, const WorkBundle& wb) {
1060 status = static_cast<c2_status_t>(s);
1061 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001062 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001063 return;
1064 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001065 if (!objcpy(flushedWork, wb)) {
1066 status = C2_CORRUPTED;
1067 } else {
1068 status = C2_OK;
1069 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001070 });
1071 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001072 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001073 return C2_TRANSACTION_FAILED;
1074 }
1075
1076 // Indices of flushed work items.
1077 std::vector<uint64_t> flushedIndices;
1078 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
1079 if (work) {
1080 if (work->worklets.empty()
1081 || !work->worklets.back()
1082 || (work->worklets.back()->output.flags &
1083 C2FrameData::FLAG_INCOMPLETE) == 0) {
1084 // input is complete
1085 flushedIndices.emplace_back(
1086 work->input.ordinal.frameIndex.peeku());
1087 }
1088 }
1089 }
1090
1091 // Input buffers' lifetime management
1092 for (uint64_t flushedIndex : flushedIndices) {
1093 std::lock_guard<std::mutex> lock(mInputBuffersMutex);
1094 auto it = mInputBuffers.find(flushedIndex);
1095 if (it == mInputBuffers.end()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001096 LOG(VERBOSE) << "flush -- returned consumed/unknown input frame: "
1097 "index = " << flushedIndex << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001098 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001099 LOG(VERBOSE) << "flush -- returned unprocessed input frame: "
1100 "index = " << flushedIndex
1101 << ", number of buffers = "
1102 << mInputBufferCount[flushedIndex]
1103 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001104 mInputBuffers.erase(it);
1105 mInputBufferCount.erase(flushedIndex);
1106 }
1107 }
1108
1109 // Output bufferqueue-based blocks' lifetime management
1110 mOutputBufferQueueMutex.lock();
1111 sp<IGraphicBufferProducer> igbp = mOutputIgbp;
1112 uint64_t bqId = mOutputBqId;
1113 uint32_t generation = mOutputGeneration;
1114 mOutputBufferQueueMutex.unlock();
1115
1116 if (igbp) {
1117 holdBufferQueueBlocks(*flushedWork, igbp, bqId, generation);
1118 }
1119
1120 return status;
1121}
1122
1123c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001124 Return<Status> transStatus = mBase->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001125 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1126 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001127 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001128 return C2_TRANSACTION_FAILED;
1129 }
1130 c2_status_t status =
1131 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1132 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001133 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001134 }
1135 return status;
1136}
1137
1138c2_status_t Codec2Client::Component::start() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001139 Return<Status> transStatus = mBase->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001140 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001141 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001142 return C2_TRANSACTION_FAILED;
1143 }
1144 c2_status_t status =
1145 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1146 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001147 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001148 }
1149 return status;
1150}
1151
1152c2_status_t Codec2Client::Component::stop() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001153 Return<Status> transStatus = mBase->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001154 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001155 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001156 return C2_TRANSACTION_FAILED;
1157 }
1158 c2_status_t status =
1159 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1160 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001161 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001162 }
1163 mInputBuffersMutex.lock();
1164 mInputBuffers.clear();
1165 mInputBufferCount.clear();
1166 mInputBuffersMutex.unlock();
1167 return status;
1168}
1169
1170c2_status_t Codec2Client::Component::reset() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001171 Return<Status> transStatus = mBase->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001172 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001173 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001174 return C2_TRANSACTION_FAILED;
1175 }
1176 c2_status_t status =
1177 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1178 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001179 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001180 }
1181 mInputBuffersMutex.lock();
1182 mInputBuffers.clear();
1183 mInputBufferCount.clear();
1184 mInputBuffersMutex.unlock();
1185 return status;
1186}
1187
1188c2_status_t Codec2Client::Component::release() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001189 Return<Status> transStatus = mBase->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001190 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001191 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001192 return C2_TRANSACTION_FAILED;
1193 }
1194 c2_status_t status =
1195 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1196 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001197 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001198 }
1199 mInputBuffersMutex.lock();
1200 mInputBuffers.clear();
1201 mInputBufferCount.clear();
1202 mInputBuffersMutex.unlock();
1203 return status;
1204}
1205
1206c2_status_t Codec2Client::Component::setOutputSurface(
1207 C2BlockPool::local_id_t blockPoolId,
1208 const sp<IGraphicBufferProducer>& surface,
1209 uint32_t generation) {
1210 sp<HGraphicBufferProducer> igbp = surface->getHalInterface();
1211 if (!igbp) {
1212 igbp = new TWGraphicBufferProducer<HGraphicBufferProducer>(surface);
1213 }
1214
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001215 Return<Status> transStatus = mBase->setOutputSurface(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001216 static_cast<uint64_t>(blockPoolId), igbp);
1217 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001218 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001219 return C2_TRANSACTION_FAILED;
1220 }
1221 c2_status_t status =
1222 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1223 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001224 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001225 } else {
1226 std::lock_guard<std::mutex> lock(mOutputBufferQueueMutex);
1227 if (mOutputIgbp != surface) {
1228 mOutputIgbp = surface;
1229 if (!surface) {
1230 mOutputBqId = 0;
1231 } else if (surface->getUniqueId(&mOutputBqId) != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001232 LOG(ERROR) << "setOutputSurface -- "
1233 "cannot obtain bufferqueue id.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001234 }
1235 }
1236 mOutputGeneration = generation;
1237 }
1238 return status;
1239}
1240
1241status_t Codec2Client::Component::queueToOutputSurface(
1242 const C2ConstGraphicBlock& block,
1243 const QueueBufferInput& input,
1244 QueueBufferOutput* output) {
1245 uint32_t generation;
1246 uint64_t bqId;
1247 int32_t bqSlot;
1248 if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot) ||
1249 bqId == 0) {
1250 // Block not from bufferqueue -- it must be attached before queuing.
1251
1252 mOutputBufferQueueMutex.lock();
1253 sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp;
1254 uint32_t outputGeneration = mOutputGeneration;
1255 mOutputBufferQueueMutex.unlock();
1256
Sungtak Lee9b148812019-01-27 16:30:13 -08001257 status_t status = attachToBufferQueue(block,
Pawin Vongmasa36653902018-11-15 00:10:25 -08001258 outputIgbp,
1259 outputGeneration,
1260 &bqSlot);
1261 if (status != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001262 LOG(WARNING) << "queueToOutputSurface -- attaching failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001263 return INVALID_OPERATION;
1264 }
1265
1266 status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
1267 input, output);
1268 if (status != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001269 LOG(ERROR) << "queueToOutputSurface -- queueBuffer() failed "
1270 "on non-bufferqueue-based block. "
1271 "Error = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001272 return status;
1273 }
1274 return OK;
1275 }
1276
1277 mOutputBufferQueueMutex.lock();
1278 sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp;
1279 uint64_t outputBqId = mOutputBqId;
1280 uint32_t outputGeneration = mOutputGeneration;
1281 mOutputBufferQueueMutex.unlock();
1282
1283 if (!outputIgbp) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001284 LOG(VERBOSE) << "queueToOutputSurface -- output surface is null.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001285 return NO_INIT;
1286 }
1287
Sungtak Lee9b148812019-01-27 16:30:13 -08001288 if (bqId != outputBqId || generation != outputGeneration) {
1289 if (!holdBufferQueueBlock(block, mOutputIgbp, mOutputBqId, mOutputGeneration)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001290 LOG(ERROR) << "queueToOutputSurface -- migration failed.";
Sungtak Lee9b148812019-01-27 16:30:13 -08001291 return DEAD_OBJECT;
1292 }
1293 if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001294 LOG(ERROR) << "queueToOutputSurface -- corrupted bufferqueue assignment.";
Sungtak Lee9b148812019-01-27 16:30:13 -08001295 return UNKNOWN_ERROR;
1296 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001297 }
1298
1299 status_t status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
1300 input, output);
1301 if (status != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001302 LOG(DEBUG) << "queueToOutputSurface -- queueBuffer() failed "
1303 "on bufferqueue-based block. "
1304 "Error = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001305 return status;
1306 }
1307 if (!yieldBufferQueueBlock(block)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001308 LOG(DEBUG) << "queueToOutputSurface -- cannot yield "
1309 "bufferqueue-based block to the bufferqueue.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001310 return UNKNOWN_ERROR;
1311 }
1312 return OK;
1313}
1314
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001315c2_status_t Codec2Client::Component::connectToInputSurface(
1316 const std::shared_ptr<InputSurface>& inputSurface,
1317 std::shared_ptr<InputSurfaceConnection>* connection) {
1318 c2_status_t status;
1319 Return<void> transStatus = mBase->connectToInputSurface(
1320 inputSurface->mBase,
1321 [&status, connection](
1322 Status s, const sp<IInputSurfaceConnection>& c) {
1323 status = static_cast<c2_status_t>(s);
1324 if (status != C2_OK) {
1325 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1326 << status << ".";
1327 return;
1328 }
1329 *connection = std::make_shared<InputSurfaceConnection>(c);
1330 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001331 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001332 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001333 return C2_TRANSACTION_FAILED;
1334 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001335 return status;
1336}
1337
1338c2_status_t Codec2Client::Component::connectToOmxInputSurface(
1339 const sp<HGraphicBufferProducer>& producer,
1340 const sp<HGraphicBufferSource>& source,
1341 std::shared_ptr<InputSurfaceConnection>* connection) {
1342 c2_status_t status;
1343 Return<void> transStatus = mBase->connectToOmxInputSurface(
1344 producer, source,
1345 [&status, connection](
1346 Status s, const sp<IInputSurfaceConnection>& c) {
1347 status = static_cast<c2_status_t>(s);
1348 if (status != C2_OK) {
1349 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1350 << status << ".";
1351 return;
1352 }
1353 *connection = std::make_shared<InputSurfaceConnection>(c);
1354 });
1355 if (!transStatus.isOk()) {
1356 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1357 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001358 }
1359 return status;
1360}
1361
1362c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001363 Return<Status> transStatus = mBase->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001364 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001365 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001366 return C2_TRANSACTION_FAILED;
1367 }
1368 c2_status_t status =
1369 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1370 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001371 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1372 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001373 }
1374 return status;
1375}
1376
1377c2_status_t Codec2Client::Component::setDeathListener(
1378 const std::shared_ptr<Component>& component,
1379 const std::shared_ptr<Listener>& listener) {
1380
1381 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1382 std::weak_ptr<Component> component;
1383 std::weak_ptr<Listener> base;
1384
1385 virtual void serviceDied(
1386 uint64_t /* cookie */,
1387 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1388 ) override {
1389 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1390 listener->onDeath(component);
1391 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001392 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001393 }
1394 }
1395 };
1396
1397 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1398 deathRecipient->base = listener;
1399 deathRecipient->component = component;
1400
1401 component->mDeathRecipient = deathRecipient;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001402 Return<bool> transResult = component->mBase->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001403 component->mDeathRecipient, 0);
1404 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001405 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001406 return C2_TRANSACTION_FAILED;
1407 }
1408 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001409 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001410 return C2_CORRUPTED;
1411 }
1412 return C2_OK;
1413}
1414
1415// Codec2Client::InputSurface
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001416Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base)
1417 : Configurable{
1418 [base]() -> sp<IConfigurable> {
1419 Return<sp<IConfigurable>> transResult =
1420 base->getConfigurable();
1421 return transResult.isOk() ?
1422 static_cast<sp<IConfigurable>>(transResult) :
1423 nullptr;
1424 }()
1425 },
1426 mBase{base},
1427 mGraphicBufferProducer{new
Pawin Vongmasa36653902018-11-15 00:10:25 -08001428 ::android::hardware::graphics::bufferqueue::V1_0::utils::
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001429 H2BGraphicBufferProducer([base]() -> sp<HGraphicBufferProducer> {
1430 Return<sp<HGraphicBufferProducer>> transResult =
1431 base->getGraphicBufferProducer();
1432 return transResult.isOk() ?
1433 static_cast<sp<HGraphicBufferProducer>>(transResult) :
1434 nullptr;
1435 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001436}
1437
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001438sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08001439 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1440 return mGraphicBufferProducer;
1441}
1442
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001443sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001444 return mBase;
1445}
1446
1447// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08001448Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001449 const sp<IInputSurfaceConnection>& base)
1450 : Configurable{
1451 [base]() -> sp<IConfigurable> {
1452 Return<sp<IConfigurable>> transResult =
1453 base->getConfigurable();
1454 return transResult.isOk() ?
1455 static_cast<sp<IConfigurable>>(transResult) :
1456 nullptr;
1457 }()
1458 },
1459 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001460}
1461
1462c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001463 Return<Status> transResult = mBase->disconnect();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001464 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1465}
1466
1467} // namespace android
1468