blob: e02c2ca68b91507e63a9edec7a0c61b136ed2d19 [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
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800347 std::shared_ptr<Codec2Client::Component> strongComponent =
348 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800349 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800350 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800351 }
352 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800353 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800354 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800355 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800356 }
357 return Void();
358 }
359
360 virtual Return<void> onTripped(
361 const hidl_vec<SettingResult>& settingResults) override {
362 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
363 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800364 for (size_t i = 0; i < settingResults.size(); ++i) {
365 std::unique_ptr<C2SettingResult> c2SettingResult;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800366 if (!objcpy(&c2SettingResult, settingResults[i])) {
367 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800368 return Void();
369 }
370 c2SettingResults[i] = std::move(c2SettingResult);
371 }
372 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
373 listener->onTripped(component, c2SettingResults);
374 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800375 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800376 }
377 return Void();
378 }
379
380 virtual Return<void> onError(Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800381 LOG(DEBUG) << "onError --"
382 << " status = " << s
383 << ", errorCode = " << errorCode
384 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800385 if (std::shared_ptr<Listener> listener = base.lock()) {
386 listener->onError(component, s == Status::OK ?
387 errorCode : static_cast<c2_status_t>(s));
388 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800389 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800390 }
391 return Void();
392 }
393
394 virtual Return<void> onFramesRendered(
395 const hidl_vec<RenderedFrame>& renderedFrames) override {
396 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800397 if (!listener) {
398 LOG(DEBUG) << "onFramesRendered -- listener died.";
399 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800400 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800401 for (const RenderedFrame& renderedFrame : renderedFrames) {
402 listener->onFrameRendered(
403 renderedFrame.bufferQueueId,
404 renderedFrame.slotId,
405 renderedFrame.timestampNs);
406 }
407 return Void();
408 }
409
410 virtual Return<void> onInputBuffersReleased(
411 const hidl_vec<InputBuffer>& inputBuffers) override {
412 std::shared_ptr<Listener> listener = base.lock();
413 if (!listener) {
414 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
415 return Void();
416 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800417 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800418 LOG(VERBOSE) << "onInputBuffersReleased --"
419 " received death notification of"
420 " input buffer:"
421 " frameIndex = " << inputBuffer.frameIndex
422 << ", bufferIndex = " << inputBuffer.arrayIndex
423 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -0800424 listener->onInputBufferDone(
425 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800426 }
427 return Void();
428 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800429
Pawin Vongmasa36653902018-11-15 00:10:25 -0800430};
431
432// Codec2Client
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800433Codec2Client::Codec2Client(const sp<IComponentStore>& base,
434 std::string serviceName)
435 : Configurable{
436 [base]() -> sp<IConfigurable> {
437 Return<sp<IConfigurable>> transResult =
438 base->getConfigurable();
439 return transResult.isOk() ?
440 static_cast<sp<IConfigurable>>(transResult) :
441 nullptr;
442 }()
443 },
444 mBase{base},
445 mListed{false},
446 mServiceName{serviceName} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800447 Return<sp<IClientManager>> transResult = base->getPoolClientManager();
448 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800449 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800450 } else {
451 mHostPoolManager = static_cast<sp<IClientManager>>(transResult);
452 }
453}
454
455c2_status_t Codec2Client::createComponent(
456 const C2String& name,
457 const std::shared_ptr<Codec2Client::Listener>& listener,
458 std::shared_ptr<Codec2Client::Component>* const component) {
459
Pawin Vongmasa36653902018-11-15 00:10:25 -0800460 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800461 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800462 hidlListener->base = listener;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800463 Return<void> transStatus = mBase->createComponent(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800464 name,
465 hidlListener,
466 ClientManager::getInstance(),
467 [&status, component, hidlListener](
468 Status s,
469 const sp<IComponent>& c) {
470 status = static_cast<c2_status_t>(s);
471 if (status != C2_OK) {
472 return;
473 }
474 *component = std::make_shared<Codec2Client::Component>(c);
475 hidlListener->component = *component;
476 });
477 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800478 LOG(ERROR) << "createComponent(" << name.c_str()
479 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800480 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800481 } else if (status != C2_OK) {
482 LOG(ERROR) << "createComponent(" << name.c_str()
483 << ") -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800484 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800485 } else if (!*component) {
486 LOG(ERROR) << "createComponent(" << name.c_str()
487 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800488 return C2_CORRUPTED;
489 }
490
491 status = (*component)->setDeathListener(*component, listener);
492 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800493 LOG(ERROR) << "createComponent(" << name.c_str()
494 << ") -- failed to set up death listener: "
495 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800496 }
497
498 (*component)->mBufferPoolSender.setReceiver(mHostPoolManager);
499 return status;
500}
501
502c2_status_t Codec2Client::createInterface(
503 const C2String& name,
504 std::shared_ptr<Codec2Client::Interface>* const interface) {
505 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800506 Return<void> transStatus = mBase->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800507 name,
508 [&status, interface](
509 Status s,
510 const sp<IComponentInterface>& i) {
511 status = static_cast<c2_status_t>(s);
512 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800513 return;
514 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800515 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800516 });
517 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800518 LOG(ERROR) << "createInterface(" << name.c_str()
519 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800520 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800521 } else if (status != C2_OK) {
522 LOG(ERROR) << "createComponent(" << name.c_str()
523 << ") -- call failed: " << status << ".";
524 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800525 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800526
Pawin Vongmasa36653902018-11-15 00:10:25 -0800527 return status;
528}
529
530c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800531 std::shared_ptr<InputSurface>* const inputSurface) {
532 c2_status_t status;
533 Return<void> transStatus = mBase->createInputSurface(
534 [&status, inputSurface](
535 Status s,
536 const sp<IInputSurface>& i) {
537 status = static_cast<c2_status_t>(s);
538 if (status != C2_OK) {
539 return;
540 }
541 *inputSurface = std::make_shared<InputSurface>(i);
542 });
543 if (!transStatus.isOk()) {
544 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800545 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800546 } else if (status != C2_OK) {
547 LOG(DEBUG) << "createInputSurface -- call failed: "
548 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800549 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800550 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800551}
552
553const std::vector<C2Component::Traits>& Codec2Client::listComponents() const {
554 std::lock_guard<std::mutex> lock(mMutex);
555 if (mListed) {
556 return mTraitsList;
557 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800558 Return<void> transStatus = mBase->listComponents(
559 [this](Status s,
560 const hidl_vec<IComponentStore::ComponentTraits>& t) {
561 if (s != Status::OK) {
562 LOG(DEBUG) << "listComponents -- call failed: "
563 << static_cast<c2_status_t>(s) << ".";
564 return;
565 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800566 mTraitsList.resize(t.size());
567 mAliasesBuffer.resize(t.size());
568 for (size_t i = 0; i < t.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800569 if (!objcpy(&mTraitsList[i], &mAliasesBuffer[i], t[i])) {
570 LOG(ERROR) << "listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800571 return;
572 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800573 mTraitsList[i].owner = mServiceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800574 }
575 });
576 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800577 LOG(ERROR) << "listComponents -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800578 }
579 mListed = true;
580 return mTraitsList;
581}
582
583c2_status_t Codec2Client::copyBuffer(
584 const std::shared_ptr<C2Buffer>& src,
585 const std::shared_ptr<C2Buffer>& dst) {
586 // TODO: Implement?
587 (void)src;
588 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800589 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800590 return C2_OMITTED;
591}
592
593std::shared_ptr<C2ParamReflector>
594 Codec2Client::getParamReflector() {
595 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
596 // should reflect the HAL API.
597 struct SimpleParamReflector : public C2ParamReflector {
598 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
599 hidl_vec<ParamIndex> indices(1);
600 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
601 std::unique_ptr<C2StructDescriptor> descriptor;
602 Return<void> transStatus = mBase->getStructDescriptors(
603 indices,
604 [&descriptor](
605 Status s,
606 const hidl_vec<StructDescriptor>& sd) {
607 c2_status_t status = static_cast<c2_status_t>(s);
608 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800609 LOG(DEBUG) << "SimpleParamReflector -- "
610 "getStructDescriptors() failed: "
611 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800612 descriptor.reset();
613 return;
614 }
615 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800616 LOG(DEBUG) << "SimpleParamReflector -- "
617 "getStructDescriptors() "
618 "returned vector of size "
619 << sd.size() << ". "
620 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800621 descriptor.reset();
622 return;
623 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800624 if (!objcpy(&descriptor, sd[0])) {
625 LOG(DEBUG) << "SimpleParamReflector -- "
626 "getStructDescriptors() returned "
627 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800628 descriptor.reset();
629 return;
630 }
631 });
632 return descriptor;
633 }
634
635 SimpleParamReflector(sp<Base> base)
636 : mBase(base) { }
637
638 sp<Base> mBase;
639 };
640
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800641 return std::make_shared<SimpleParamReflector>(mBase);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800642};
643
644std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800645 const char* serviceName, bool waitForService) {
646 if (!serviceName) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800647 return nullptr;
648 }
649 sp<Base> baseStore = waitForService ?
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800650 Base::getService(serviceName) :
651 Base::tryGetService(serviceName);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800652 if (!baseStore) {
653 if (waitForService) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800654 LOG(WARNING) << "Codec2.0 service \"" << serviceName << "\""
655 " inaccessible. Check the device manifest.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800656 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800657 LOG(DEBUG) << "Codec2.0 service \"" << serviceName << "\""
658 " unavailable at the moment. "
659 " Wait or check the device manifest.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800660 }
661 return nullptr;
662 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800663 return std::make_shared<Codec2Client>(baseStore, serviceName);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800664}
665
666c2_status_t Codec2Client::ForAllStores(
667 const std::string &key,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800668 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
669 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800670 c2_status_t status = C2_NO_INIT; // no IComponentStores present
671
672 // Cache the mapping key -> index of Codec2Client in getClient().
673 static std::mutex key2IndexMutex;
674 static std::map<std::string, size_t> key2Index;
675
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800676 // By default try all stores. However, try the last known client first. If
677 // the last known client fails, retry once. We do this by pushing the last
678 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800679 std::deque<size_t> indices;
680 for (size_t index = kNumClients; index > 0; ) {
681 indices.push_front(--index);
682 }
683
684 bool wasMapped = false;
685 std::unique_lock<std::mutex> lock(key2IndexMutex);
686 auto it = key2Index.find(key);
687 if (it != key2Index.end()) {
688 indices.push_front(it->second);
689 wasMapped = true;
690 }
691 lock.unlock();
692
693 for (size_t index : indices) {
694 std::shared_ptr<Codec2Client> client = getClient(index);
695 if (client) {
696 status = predicate(client);
697 if (status == C2_OK) {
698 lock.lock();
699 key2Index[key] = index; // update last known client index
700 return status;
701 }
702 }
703 if (wasMapped) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800704 LOG(INFO) << "Could not find \"" << key << "\""
705 " in the last instance. Retrying...";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800706 wasMapped = false;
707 }
708 }
709 return status; // return the last status from a valid client
710}
711
712std::shared_ptr<Codec2Client::Component>
713 Codec2Client::CreateComponentByName(
714 const char* componentName,
715 const std::shared_ptr<Listener>& listener,
716 std::shared_ptr<Codec2Client>* owner) {
717 std::shared_ptr<Component> component;
718 c2_status_t status = ForAllStores(
719 componentName,
720 [owner, &component, componentName, &listener](
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800721 const std::shared_ptr<Codec2Client> &client)
722 -> c2_status_t {
723 c2_status_t status = client->createComponent(componentName,
724 listener,
725 &component);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800726 if (status == C2_OK) {
727 if (owner) {
728 *owner = client;
729 }
730 } else if (status != C2_NOT_FOUND) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800731 LOG(DEBUG) << "IComponentStore("
732 << client->getServiceName()
733 << ")::createComponent(\"" << componentName
734 << "\") returned status = "
735 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800736 }
737 return status;
738 });
739 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800740 LOG(DEBUG) << "Could not create component \"" << componentName << "\". "
741 "Status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800742 }
743 return component;
744}
745
746std::shared_ptr<Codec2Client::Interface>
747 Codec2Client::CreateInterfaceByName(
748 const char* interfaceName,
749 std::shared_ptr<Codec2Client>* owner) {
750 std::shared_ptr<Interface> interface;
751 c2_status_t status = ForAllStores(
752 interfaceName,
753 [owner, &interface, interfaceName](
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800754 const std::shared_ptr<Codec2Client> &client)
755 -> c2_status_t {
756 c2_status_t status = client->createInterface(interfaceName,
757 &interface);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800758 if (status == C2_OK) {
759 if (owner) {
760 *owner = client;
761 }
762 } else if (status != C2_NOT_FOUND) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800763 LOG(DEBUG) << "IComponentStore("
764 << client->getServiceName()
765 << ")::createInterface(\"" << interfaceName
766 << "\") returned status = "
767 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800768 }
769 return status;
770 });
771 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800772 LOG(DEBUG) << "Could not create interface \"" << interfaceName << "\". "
773 "Status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800774 }
775 return interface;
776}
777
778std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface() {
779 uint32_t serviceMask = ::android::base::GetUintProperty(
780 "debug.stagefright.c2inputsurface", uint32_t(0));
781 for (size_t i = 0; i < kNumClients; ++i) {
782 if ((1 << i) & serviceMask) {
783 std::shared_ptr<Codec2Client> client = getClient(i);
784 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
785 if (client &&
786 client->createInputSurface(&inputSurface) == C2_OK &&
787 inputSurface) {
788 return inputSurface;
789 }
790 }
791 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800792 LOG(INFO) << "Could not create an input surface "
793 "from any Codec2.0 services.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800794 return nullptr;
795}
796
797const std::vector<C2Component::Traits>& Codec2Client::ListComponents() {
798 static std::vector<C2Component::Traits> traitsList = [](){
799 std::vector<C2Component::Traits> list;
800 size_t listSize = 0;
801 ClientList clientList = getClientList();
802 for (const std::shared_ptr<Codec2Client>& client : clientList) {
803 if (!client) {
804 continue;
805 }
806 listSize += client->listComponents().size();
807 }
808 list.reserve(listSize);
809 for (const std::shared_ptr<Codec2Client>& client : clientList) {
810 if (!client) {
811 continue;
812 }
813 list.insert(
814 list.end(),
815 client->listComponents().begin(),
816 client->listComponents().end());
817 }
818 return list;
819 }();
820
821 return traitsList;
822}
823
824// Codec2Client::Listener
825
826Codec2Client::Listener::~Listener() {
827}
828
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800829// Codec2Client::Interface
830Codec2Client::Interface::Interface(const sp<Base>& base)
831 : Configurable{
832 [base]() -> sp<IConfigurable> {
833 Return<sp<IConfigurable>> transResult =
834 base->getConfigurable();
835 return transResult.isOk() ?
836 static_cast<sp<IConfigurable>>(transResult) :
837 nullptr;
838 }()
839 },
840 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800841}
842
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800843// Codec2Client::Component
844Codec2Client::Component::Component(const sp<Base>& base)
845 : Configurable{
846 [base]() -> sp<IConfigurable> {
847 Return<sp<IComponentInterface>> transResult1 =
848 base->getInterface();
849 if (!transResult1.isOk()) {
850 return nullptr;
851 }
852 Return<sp<IConfigurable>> transResult2 =
853 static_cast<sp<IComponentInterface>>(transResult1)->
854 getConfigurable();
855 return transResult2.isOk() ?
856 static_cast<sp<IConfigurable>>(transResult2) :
857 nullptr;
858 }()
859 },
860 mBase{base},
861 mBufferPoolSender{nullptr} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800862}
863
864Codec2Client::Component::~Component() {
865}
866
867c2_status_t Codec2Client::Component::createBlockPool(
868 C2Allocator::id_t id,
869 C2BlockPool::local_id_t* blockPoolId,
870 std::shared_ptr<Codec2Client::Configurable>* configurable) {
871 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800872 Return<void> transStatus = mBase->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800873 static_cast<uint32_t>(id),
874 [&status, blockPoolId, configurable](
875 Status s,
876 uint64_t pId,
877 const sp<IConfigurable>& c) {
878 status = static_cast<c2_status_t>(s);
879 configurable->reset();
880 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800881 LOG(DEBUG) << "createBlockPool -- call failed: "
882 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800883 return;
884 }
885 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800886 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800887 });
888 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800889 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800890 return C2_TRANSACTION_FAILED;
891 }
892 return status;
893}
894
895c2_status_t Codec2Client::Component::destroyBlockPool(
896 C2BlockPool::local_id_t localId) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800897 Return<Status> transResult = mBase->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800898 static_cast<uint64_t>(localId));
899 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800900 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800901 return C2_TRANSACTION_FAILED;
902 }
903 return static_cast<c2_status_t>(static_cast<Status>(transResult));
904}
905
Wonsik Kimab34ed62019-01-31 15:28:46 -0800906void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800907 const std::list<std::unique_ptr<C2Work>> &workItems) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800908 // Output bufferqueue-based blocks' lifetime management
909 mOutputBufferQueueMutex.lock();
910 sp<IGraphicBufferProducer> igbp = mOutputIgbp;
911 uint64_t bqId = mOutputBqId;
912 uint32_t generation = mOutputGeneration;
913 mOutputBufferQueueMutex.unlock();
914
915 if (igbp) {
916 holdBufferQueueBlocks(workItems, igbp, bqId, generation);
917 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800918}
919
920c2_status_t Codec2Client::Component::queue(
921 std::list<std::unique_ptr<C2Work>>* const items) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800922 WorkBundle workBundle;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800923 if (!objcpy(&workBundle, *items, &mBufferPoolSender)) {
924 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800925 return C2_TRANSACTION_FAILED;
926 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800927 Return<Status> transStatus = mBase->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800928 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800929 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800930 return C2_TRANSACTION_FAILED;
931 }
932 c2_status_t status =
933 static_cast<c2_status_t>(static_cast<Status>(transStatus));
934 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800935 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800936 }
937 return status;
938}
939
940c2_status_t Codec2Client::Component::flush(
941 C2Component::flush_mode_t mode,
942 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
943 (void)mode; // Flush mode isn't supported in HIDL yet.
944 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800945 Return<void> transStatus = mBase->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800946 [&status, flushedWork](
947 Status s, const WorkBundle& wb) {
948 status = static_cast<c2_status_t>(s);
949 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800950 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800951 return;
952 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800953 if (!objcpy(flushedWork, wb)) {
954 status = C2_CORRUPTED;
955 } else {
956 status = C2_OK;
957 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800958 });
959 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800960 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800961 return C2_TRANSACTION_FAILED;
962 }
963
964 // Indices of flushed work items.
965 std::vector<uint64_t> flushedIndices;
966 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
967 if (work) {
968 if (work->worklets.empty()
969 || !work->worklets.back()
970 || (work->worklets.back()->output.flags &
971 C2FrameData::FLAG_INCOMPLETE) == 0) {
972 // input is complete
973 flushedIndices.emplace_back(
974 work->input.ordinal.frameIndex.peeku());
975 }
976 }
977 }
978
Pawin Vongmasa36653902018-11-15 00:10:25 -0800979 // Output bufferqueue-based blocks' lifetime management
980 mOutputBufferQueueMutex.lock();
981 sp<IGraphicBufferProducer> igbp = mOutputIgbp;
982 uint64_t bqId = mOutputBqId;
983 uint32_t generation = mOutputGeneration;
984 mOutputBufferQueueMutex.unlock();
985
986 if (igbp) {
987 holdBufferQueueBlocks(*flushedWork, igbp, bqId, generation);
988 }
989
990 return status;
991}
992
993c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800994 Return<Status> transStatus = mBase->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800995 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
996 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800997 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800998 return C2_TRANSACTION_FAILED;
999 }
1000 c2_status_t status =
1001 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1002 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001003 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001004 }
1005 return status;
1006}
1007
1008c2_status_t Codec2Client::Component::start() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001009 Return<Status> transStatus = mBase->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001010 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001011 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001012 return C2_TRANSACTION_FAILED;
1013 }
1014 c2_status_t status =
1015 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1016 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001017 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001018 }
1019 return status;
1020}
1021
1022c2_status_t Codec2Client::Component::stop() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001023 Return<Status> transStatus = mBase->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001024 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001025 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001026 return C2_TRANSACTION_FAILED;
1027 }
1028 c2_status_t status =
1029 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1030 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001031 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001032 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001033 return status;
1034}
1035
1036c2_status_t Codec2Client::Component::reset() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001037 Return<Status> transStatus = mBase->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001038 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001039 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001040 return C2_TRANSACTION_FAILED;
1041 }
1042 c2_status_t status =
1043 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1044 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001045 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001046 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001047 return status;
1048}
1049
1050c2_status_t Codec2Client::Component::release() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001051 Return<Status> transStatus = mBase->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001052 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001053 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001054 return C2_TRANSACTION_FAILED;
1055 }
1056 c2_status_t status =
1057 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1058 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001059 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001060 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001061 return status;
1062}
1063
1064c2_status_t Codec2Client::Component::setOutputSurface(
1065 C2BlockPool::local_id_t blockPoolId,
1066 const sp<IGraphicBufferProducer>& surface,
1067 uint32_t generation) {
1068 sp<HGraphicBufferProducer> igbp = surface->getHalInterface();
1069 if (!igbp) {
1070 igbp = new TWGraphicBufferProducer<HGraphicBufferProducer>(surface);
1071 }
1072
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001073 Return<Status> transStatus = mBase->setOutputSurface(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001074 static_cast<uint64_t>(blockPoolId), igbp);
1075 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001076 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001077 return C2_TRANSACTION_FAILED;
1078 }
1079 c2_status_t status =
1080 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1081 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001082 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001083 } else {
1084 std::lock_guard<std::mutex> lock(mOutputBufferQueueMutex);
1085 if (mOutputIgbp != surface) {
1086 mOutputIgbp = surface;
1087 if (!surface) {
1088 mOutputBqId = 0;
1089 } else if (surface->getUniqueId(&mOutputBqId) != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001090 LOG(ERROR) << "setOutputSurface -- "
1091 "cannot obtain bufferqueue id.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001092 }
1093 }
1094 mOutputGeneration = generation;
1095 }
1096 return status;
1097}
1098
1099status_t Codec2Client::Component::queueToOutputSurface(
1100 const C2ConstGraphicBlock& block,
1101 const QueueBufferInput& input,
1102 QueueBufferOutput* output) {
1103 uint32_t generation;
1104 uint64_t bqId;
1105 int32_t bqSlot;
1106 if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot) ||
1107 bqId == 0) {
1108 // Block not from bufferqueue -- it must be attached before queuing.
1109
1110 mOutputBufferQueueMutex.lock();
1111 sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp;
1112 uint32_t outputGeneration = mOutputGeneration;
1113 mOutputBufferQueueMutex.unlock();
1114
Sungtak Lee9b148812019-01-27 16:30:13 -08001115 status_t status = attachToBufferQueue(block,
Pawin Vongmasa36653902018-11-15 00:10:25 -08001116 outputIgbp,
1117 outputGeneration,
1118 &bqSlot);
1119 if (status != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001120 LOG(WARNING) << "queueToOutputSurface -- attaching failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001121 return INVALID_OPERATION;
1122 }
1123
1124 status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
1125 input, output);
1126 if (status != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001127 LOG(ERROR) << "queueToOutputSurface -- queueBuffer() failed "
1128 "on non-bufferqueue-based block. "
1129 "Error = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001130 return status;
1131 }
1132 return OK;
1133 }
1134
1135 mOutputBufferQueueMutex.lock();
1136 sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp;
1137 uint64_t outputBqId = mOutputBqId;
1138 uint32_t outputGeneration = mOutputGeneration;
1139 mOutputBufferQueueMutex.unlock();
1140
1141 if (!outputIgbp) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001142 LOG(VERBOSE) << "queueToOutputSurface -- output surface is null.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001143 return NO_INIT;
1144 }
1145
Sungtak Lee9b148812019-01-27 16:30:13 -08001146 if (bqId != outputBqId || generation != outputGeneration) {
1147 if (!holdBufferQueueBlock(block, mOutputIgbp, mOutputBqId, mOutputGeneration)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001148 LOG(ERROR) << "queueToOutputSurface -- migration failed.";
Sungtak Lee9b148812019-01-27 16:30:13 -08001149 return DEAD_OBJECT;
1150 }
1151 if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001152 LOG(ERROR) << "queueToOutputSurface -- corrupted bufferqueue assignment.";
Sungtak Lee9b148812019-01-27 16:30:13 -08001153 return UNKNOWN_ERROR;
1154 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001155 }
1156
1157 status_t status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
1158 input, output);
1159 if (status != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001160 LOG(DEBUG) << "queueToOutputSurface -- queueBuffer() failed "
1161 "on bufferqueue-based block. "
1162 "Error = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001163 return status;
1164 }
1165 if (!yieldBufferQueueBlock(block)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001166 LOG(DEBUG) << "queueToOutputSurface -- cannot yield "
1167 "bufferqueue-based block to the bufferqueue.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001168 return UNKNOWN_ERROR;
1169 }
1170 return OK;
1171}
1172
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001173c2_status_t Codec2Client::Component::connectToInputSurface(
1174 const std::shared_ptr<InputSurface>& inputSurface,
1175 std::shared_ptr<InputSurfaceConnection>* connection) {
1176 c2_status_t status;
1177 Return<void> transStatus = mBase->connectToInputSurface(
1178 inputSurface->mBase,
1179 [&status, connection](
1180 Status s, const sp<IInputSurfaceConnection>& c) {
1181 status = static_cast<c2_status_t>(s);
1182 if (status != C2_OK) {
1183 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1184 << status << ".";
1185 return;
1186 }
1187 *connection = std::make_shared<InputSurfaceConnection>(c);
1188 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001189 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001190 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001191 return C2_TRANSACTION_FAILED;
1192 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001193 return status;
1194}
1195
1196c2_status_t Codec2Client::Component::connectToOmxInputSurface(
1197 const sp<HGraphicBufferProducer>& producer,
1198 const sp<HGraphicBufferSource>& source,
1199 std::shared_ptr<InputSurfaceConnection>* connection) {
1200 c2_status_t status;
1201 Return<void> transStatus = mBase->connectToOmxInputSurface(
1202 producer, source,
1203 [&status, connection](
1204 Status s, const sp<IInputSurfaceConnection>& c) {
1205 status = static_cast<c2_status_t>(s);
1206 if (status != C2_OK) {
1207 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1208 << status << ".";
1209 return;
1210 }
1211 *connection = std::make_shared<InputSurfaceConnection>(c);
1212 });
1213 if (!transStatus.isOk()) {
1214 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1215 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001216 }
1217 return status;
1218}
1219
1220c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001221 Return<Status> transStatus = mBase->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001222 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001223 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001224 return C2_TRANSACTION_FAILED;
1225 }
1226 c2_status_t status =
1227 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1228 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001229 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1230 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001231 }
1232 return status;
1233}
1234
1235c2_status_t Codec2Client::Component::setDeathListener(
1236 const std::shared_ptr<Component>& component,
1237 const std::shared_ptr<Listener>& listener) {
1238
1239 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1240 std::weak_ptr<Component> component;
1241 std::weak_ptr<Listener> base;
1242
1243 virtual void serviceDied(
1244 uint64_t /* cookie */,
1245 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1246 ) override {
1247 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1248 listener->onDeath(component);
1249 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001250 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001251 }
1252 }
1253 };
1254
1255 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1256 deathRecipient->base = listener;
1257 deathRecipient->component = component;
1258
1259 component->mDeathRecipient = deathRecipient;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001260 Return<bool> transResult = component->mBase->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001261 component->mDeathRecipient, 0);
1262 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001263 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001264 return C2_TRANSACTION_FAILED;
1265 }
1266 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001267 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001268 return C2_CORRUPTED;
1269 }
1270 return C2_OK;
1271}
1272
1273// Codec2Client::InputSurface
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001274Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base)
1275 : Configurable{
1276 [base]() -> sp<IConfigurable> {
1277 Return<sp<IConfigurable>> transResult =
1278 base->getConfigurable();
1279 return transResult.isOk() ?
1280 static_cast<sp<IConfigurable>>(transResult) :
1281 nullptr;
1282 }()
1283 },
1284 mBase{base},
1285 mGraphicBufferProducer{new
Pawin Vongmasa36653902018-11-15 00:10:25 -08001286 ::android::hardware::graphics::bufferqueue::V1_0::utils::
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001287 H2BGraphicBufferProducer([base]() -> sp<HGraphicBufferProducer> {
1288 Return<sp<HGraphicBufferProducer>> transResult =
1289 base->getGraphicBufferProducer();
1290 return transResult.isOk() ?
1291 static_cast<sp<HGraphicBufferProducer>>(transResult) :
1292 nullptr;
1293 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001294}
1295
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001296sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08001297 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1298 return mGraphicBufferProducer;
1299}
1300
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001301sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001302 return mBase;
1303}
1304
1305// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08001306Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001307 const sp<IInputSurfaceConnection>& base)
1308 : Configurable{
1309 [base]() -> sp<IConfigurable> {
1310 Return<sp<IConfigurable>> transResult =
1311 base->getConfigurable();
1312 return transResult.isOk() ?
1313 static_cast<sp<IConfigurable>>(transResult) :
1314 nullptr;
1315 }()
1316 },
1317 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001318}
1319
1320c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001321 Return<Status> transResult = mBase->disconnect();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001322 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1323}
1324
1325} // namespace android
1326