blob: 7a2e549f4bf4fafda6053445cf24cfe58db0c611 [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());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800567 for (size_t i = 0; i < t.size(); ++i) {
Lajos Molnar8b5c20c2019-01-31 16:15:08 -0800568 if (!objcpy(&mTraitsList[i], t[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800569 LOG(ERROR) << "listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800570 return;
571 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800572 mTraitsList[i].owner = mServiceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800573 }
574 });
575 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800576 LOG(ERROR) << "listComponents -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800577 }
578 mListed = true;
579 return mTraitsList;
580}
581
582c2_status_t Codec2Client::copyBuffer(
583 const std::shared_ptr<C2Buffer>& src,
584 const std::shared_ptr<C2Buffer>& dst) {
585 // TODO: Implement?
586 (void)src;
587 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800588 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800589 return C2_OMITTED;
590}
591
592std::shared_ptr<C2ParamReflector>
593 Codec2Client::getParamReflector() {
594 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
595 // should reflect the HAL API.
596 struct SimpleParamReflector : public C2ParamReflector {
597 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
598 hidl_vec<ParamIndex> indices(1);
599 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
600 std::unique_ptr<C2StructDescriptor> descriptor;
601 Return<void> transStatus = mBase->getStructDescriptors(
602 indices,
603 [&descriptor](
604 Status s,
605 const hidl_vec<StructDescriptor>& sd) {
606 c2_status_t status = static_cast<c2_status_t>(s);
607 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800608 LOG(DEBUG) << "SimpleParamReflector -- "
609 "getStructDescriptors() failed: "
610 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800611 descriptor.reset();
612 return;
613 }
614 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800615 LOG(DEBUG) << "SimpleParamReflector -- "
616 "getStructDescriptors() "
617 "returned vector of size "
618 << sd.size() << ". "
619 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800620 descriptor.reset();
621 return;
622 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800623 if (!objcpy(&descriptor, sd[0])) {
624 LOG(DEBUG) << "SimpleParamReflector -- "
625 "getStructDescriptors() returned "
626 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800627 descriptor.reset();
628 return;
629 }
630 });
631 return descriptor;
632 }
633
634 SimpleParamReflector(sp<Base> base)
635 : mBase(base) { }
636
637 sp<Base> mBase;
638 };
639
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800640 return std::make_shared<SimpleParamReflector>(mBase);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800641};
642
643std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800644 const char* serviceName, bool waitForService) {
645 if (!serviceName) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800646 return nullptr;
647 }
648 sp<Base> baseStore = waitForService ?
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800649 Base::getService(serviceName) :
650 Base::tryGetService(serviceName);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800651 if (!baseStore) {
652 if (waitForService) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800653 LOG(WARNING) << "Codec2.0 service \"" << serviceName << "\""
654 " inaccessible. Check the device manifest.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800655 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800656 LOG(DEBUG) << "Codec2.0 service \"" << serviceName << "\""
657 " unavailable at the moment. "
658 " Wait or check the device manifest.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800659 }
660 return nullptr;
661 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800662 return std::make_shared<Codec2Client>(baseStore, serviceName);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800663}
664
665c2_status_t Codec2Client::ForAllStores(
666 const std::string &key,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800667 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
668 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800669 c2_status_t status = C2_NO_INIT; // no IComponentStores present
670
671 // Cache the mapping key -> index of Codec2Client in getClient().
672 static std::mutex key2IndexMutex;
673 static std::map<std::string, size_t> key2Index;
674
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800675 // By default try all stores. However, try the last known client first. If
676 // the last known client fails, retry once. We do this by pushing the last
677 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800678 std::deque<size_t> indices;
679 for (size_t index = kNumClients; index > 0; ) {
680 indices.push_front(--index);
681 }
682
683 bool wasMapped = false;
684 std::unique_lock<std::mutex> lock(key2IndexMutex);
685 auto it = key2Index.find(key);
686 if (it != key2Index.end()) {
687 indices.push_front(it->second);
688 wasMapped = true;
689 }
690 lock.unlock();
691
692 for (size_t index : indices) {
693 std::shared_ptr<Codec2Client> client = getClient(index);
694 if (client) {
695 status = predicate(client);
696 if (status == C2_OK) {
697 lock.lock();
698 key2Index[key] = index; // update last known client index
699 return status;
700 }
701 }
702 if (wasMapped) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800703 LOG(INFO) << "Could not find \"" << key << "\""
704 " in the last instance. Retrying...";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800705 wasMapped = false;
706 }
707 }
708 return status; // return the last status from a valid client
709}
710
711std::shared_ptr<Codec2Client::Component>
712 Codec2Client::CreateComponentByName(
713 const char* componentName,
714 const std::shared_ptr<Listener>& listener,
715 std::shared_ptr<Codec2Client>* owner) {
716 std::shared_ptr<Component> component;
717 c2_status_t status = ForAllStores(
718 componentName,
719 [owner, &component, componentName, &listener](
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800720 const std::shared_ptr<Codec2Client> &client)
721 -> c2_status_t {
722 c2_status_t status = client->createComponent(componentName,
723 listener,
724 &component);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800725 if (status == C2_OK) {
726 if (owner) {
727 *owner = client;
728 }
729 } else if (status != C2_NOT_FOUND) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800730 LOG(DEBUG) << "IComponentStore("
731 << client->getServiceName()
732 << ")::createComponent(\"" << componentName
733 << "\") returned status = "
734 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800735 }
736 return status;
737 });
738 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800739 LOG(DEBUG) << "Could not create component \"" << componentName << "\". "
740 "Status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800741 }
742 return component;
743}
744
745std::shared_ptr<Codec2Client::Interface>
746 Codec2Client::CreateInterfaceByName(
747 const char* interfaceName,
748 std::shared_ptr<Codec2Client>* owner) {
749 std::shared_ptr<Interface> interface;
750 c2_status_t status = ForAllStores(
751 interfaceName,
752 [owner, &interface, interfaceName](
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800753 const std::shared_ptr<Codec2Client> &client)
754 -> c2_status_t {
755 c2_status_t status = client->createInterface(interfaceName,
756 &interface);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800757 if (status == C2_OK) {
758 if (owner) {
759 *owner = client;
760 }
761 } else if (status != C2_NOT_FOUND) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800762 LOG(DEBUG) << "IComponentStore("
763 << client->getServiceName()
764 << ")::createInterface(\"" << interfaceName
765 << "\") returned status = "
766 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800767 }
768 return status;
769 });
770 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800771 LOG(DEBUG) << "Could not create interface \"" << interfaceName << "\". "
772 "Status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800773 }
774 return interface;
775}
776
777std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface() {
778 uint32_t serviceMask = ::android::base::GetUintProperty(
779 "debug.stagefright.c2inputsurface", uint32_t(0));
780 for (size_t i = 0; i < kNumClients; ++i) {
781 if ((1 << i) & serviceMask) {
782 std::shared_ptr<Codec2Client> client = getClient(i);
783 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
784 if (client &&
785 client->createInputSurface(&inputSurface) == C2_OK &&
786 inputSurface) {
787 return inputSurface;
788 }
789 }
790 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800791 LOG(INFO) << "Could not create an input surface "
792 "from any Codec2.0 services.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800793 return nullptr;
794}
795
796const std::vector<C2Component::Traits>& Codec2Client::ListComponents() {
797 static std::vector<C2Component::Traits> traitsList = [](){
798 std::vector<C2Component::Traits> list;
799 size_t listSize = 0;
800 ClientList clientList = getClientList();
801 for (const std::shared_ptr<Codec2Client>& client : clientList) {
802 if (!client) {
803 continue;
804 }
805 listSize += client->listComponents().size();
806 }
807 list.reserve(listSize);
808 for (const std::shared_ptr<Codec2Client>& client : clientList) {
809 if (!client) {
810 continue;
811 }
812 list.insert(
813 list.end(),
814 client->listComponents().begin(),
815 client->listComponents().end());
816 }
817 return list;
818 }();
819
820 return traitsList;
821}
822
823// Codec2Client::Listener
824
825Codec2Client::Listener::~Listener() {
826}
827
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800828// Codec2Client::Interface
829Codec2Client::Interface::Interface(const sp<Base>& base)
830 : Configurable{
831 [base]() -> sp<IConfigurable> {
832 Return<sp<IConfigurable>> transResult =
833 base->getConfigurable();
834 return transResult.isOk() ?
835 static_cast<sp<IConfigurable>>(transResult) :
836 nullptr;
837 }()
838 },
839 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800840}
841
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800842// Codec2Client::Component
843Codec2Client::Component::Component(const sp<Base>& base)
844 : Configurable{
845 [base]() -> sp<IConfigurable> {
846 Return<sp<IComponentInterface>> transResult1 =
847 base->getInterface();
848 if (!transResult1.isOk()) {
849 return nullptr;
850 }
851 Return<sp<IConfigurable>> transResult2 =
852 static_cast<sp<IComponentInterface>>(transResult1)->
853 getConfigurable();
854 return transResult2.isOk() ?
855 static_cast<sp<IConfigurable>>(transResult2) :
856 nullptr;
857 }()
858 },
859 mBase{base},
860 mBufferPoolSender{nullptr} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800861}
862
863Codec2Client::Component::~Component() {
864}
865
866c2_status_t Codec2Client::Component::createBlockPool(
867 C2Allocator::id_t id,
868 C2BlockPool::local_id_t* blockPoolId,
869 std::shared_ptr<Codec2Client::Configurable>* configurable) {
870 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800871 Return<void> transStatus = mBase->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800872 static_cast<uint32_t>(id),
873 [&status, blockPoolId, configurable](
874 Status s,
875 uint64_t pId,
876 const sp<IConfigurable>& c) {
877 status = static_cast<c2_status_t>(s);
878 configurable->reset();
879 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800880 LOG(DEBUG) << "createBlockPool -- call failed: "
881 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800882 return;
883 }
884 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800885 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800886 });
887 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800888 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800889 return C2_TRANSACTION_FAILED;
890 }
891 return status;
892}
893
894c2_status_t Codec2Client::Component::destroyBlockPool(
895 C2BlockPool::local_id_t localId) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800896 Return<Status> transResult = mBase->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800897 static_cast<uint64_t>(localId));
898 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800899 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800900 return C2_TRANSACTION_FAILED;
901 }
902 return static_cast<c2_status_t>(static_cast<Status>(transResult));
903}
904
Wonsik Kimab34ed62019-01-31 15:28:46 -0800905void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800906 const std::list<std::unique_ptr<C2Work>> &workItems) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800907 // Output bufferqueue-based blocks' lifetime management
908 mOutputBufferQueueMutex.lock();
909 sp<IGraphicBufferProducer> igbp = mOutputIgbp;
910 uint64_t bqId = mOutputBqId;
911 uint32_t generation = mOutputGeneration;
912 mOutputBufferQueueMutex.unlock();
913
914 if (igbp) {
915 holdBufferQueueBlocks(workItems, igbp, bqId, generation);
916 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800917}
918
919c2_status_t Codec2Client::Component::queue(
920 std::list<std::unique_ptr<C2Work>>* const items) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800921 WorkBundle workBundle;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800922 if (!objcpy(&workBundle, *items, &mBufferPoolSender)) {
923 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800924 return C2_TRANSACTION_FAILED;
925 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800926 Return<Status> transStatus = mBase->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800927 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800928 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800929 return C2_TRANSACTION_FAILED;
930 }
931 c2_status_t status =
932 static_cast<c2_status_t>(static_cast<Status>(transStatus));
933 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800934 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800935 }
936 return status;
937}
938
939c2_status_t Codec2Client::Component::flush(
940 C2Component::flush_mode_t mode,
941 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
942 (void)mode; // Flush mode isn't supported in HIDL yet.
943 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800944 Return<void> transStatus = mBase->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800945 [&status, flushedWork](
946 Status s, const WorkBundle& wb) {
947 status = static_cast<c2_status_t>(s);
948 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800949 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800950 return;
951 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800952 if (!objcpy(flushedWork, wb)) {
953 status = C2_CORRUPTED;
954 } else {
955 status = C2_OK;
956 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800957 });
958 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800959 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800960 return C2_TRANSACTION_FAILED;
961 }
962
963 // Indices of flushed work items.
964 std::vector<uint64_t> flushedIndices;
965 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
966 if (work) {
967 if (work->worklets.empty()
968 || !work->worklets.back()
969 || (work->worklets.back()->output.flags &
970 C2FrameData::FLAG_INCOMPLETE) == 0) {
971 // input is complete
972 flushedIndices.emplace_back(
973 work->input.ordinal.frameIndex.peeku());
974 }
975 }
976 }
977
Pawin Vongmasa36653902018-11-15 00:10:25 -0800978 // Output bufferqueue-based blocks' lifetime management
979 mOutputBufferQueueMutex.lock();
980 sp<IGraphicBufferProducer> igbp = mOutputIgbp;
981 uint64_t bqId = mOutputBqId;
982 uint32_t generation = mOutputGeneration;
983 mOutputBufferQueueMutex.unlock();
984
985 if (igbp) {
986 holdBufferQueueBlocks(*flushedWork, igbp, bqId, generation);
987 }
988
989 return status;
990}
991
992c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800993 Return<Status> transStatus = mBase->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800994 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
995 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800996 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800997 return C2_TRANSACTION_FAILED;
998 }
999 c2_status_t status =
1000 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1001 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001002 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001003 }
1004 return status;
1005}
1006
1007c2_status_t Codec2Client::Component::start() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001008 Return<Status> transStatus = mBase->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001009 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001010 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001011 return C2_TRANSACTION_FAILED;
1012 }
1013 c2_status_t status =
1014 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1015 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001016 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001017 }
1018 return status;
1019}
1020
1021c2_status_t Codec2Client::Component::stop() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001022 Return<Status> transStatus = mBase->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001023 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001024 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001025 return C2_TRANSACTION_FAILED;
1026 }
1027 c2_status_t status =
1028 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1029 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001030 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001031 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001032 return status;
1033}
1034
1035c2_status_t Codec2Client::Component::reset() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001036 Return<Status> transStatus = mBase->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001037 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001038 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001039 return C2_TRANSACTION_FAILED;
1040 }
1041 c2_status_t status =
1042 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1043 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001044 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001045 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001046 return status;
1047}
1048
1049c2_status_t Codec2Client::Component::release() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001050 Return<Status> transStatus = mBase->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001051 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001052 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001053 return C2_TRANSACTION_FAILED;
1054 }
1055 c2_status_t status =
1056 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1057 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001058 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001059 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001060 return status;
1061}
1062
1063c2_status_t Codec2Client::Component::setOutputSurface(
1064 C2BlockPool::local_id_t blockPoolId,
1065 const sp<IGraphicBufferProducer>& surface,
1066 uint32_t generation) {
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08001067 sp<HGraphicBufferProducer> igbp =
1068 surface->getHalInterface<HGraphicBufferProducer>();
1069
Pawin Vongmasa36653902018-11-15 00:10:25 -08001070 if (!igbp) {
1071 igbp = new TWGraphicBufferProducer<HGraphicBufferProducer>(surface);
1072 }
1073
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001074 Return<Status> transStatus = mBase->setOutputSurface(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001075 static_cast<uint64_t>(blockPoolId), igbp);
1076 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001077 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001078 return C2_TRANSACTION_FAILED;
1079 }
1080 c2_status_t status =
1081 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1082 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001083 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001084 } else {
1085 std::lock_guard<std::mutex> lock(mOutputBufferQueueMutex);
1086 if (mOutputIgbp != surface) {
1087 mOutputIgbp = surface;
1088 if (!surface) {
1089 mOutputBqId = 0;
1090 } else if (surface->getUniqueId(&mOutputBqId) != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001091 LOG(ERROR) << "setOutputSurface -- "
1092 "cannot obtain bufferqueue id.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001093 }
1094 }
1095 mOutputGeneration = generation;
1096 }
1097 return status;
1098}
1099
1100status_t Codec2Client::Component::queueToOutputSurface(
1101 const C2ConstGraphicBlock& block,
1102 const QueueBufferInput& input,
1103 QueueBufferOutput* output) {
1104 uint32_t generation;
1105 uint64_t bqId;
1106 int32_t bqSlot;
1107 if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot) ||
1108 bqId == 0) {
1109 // Block not from bufferqueue -- it must be attached before queuing.
1110
1111 mOutputBufferQueueMutex.lock();
1112 sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp;
1113 uint32_t outputGeneration = mOutputGeneration;
1114 mOutputBufferQueueMutex.unlock();
1115
Sungtak Lee9b148812019-01-27 16:30:13 -08001116 status_t status = attachToBufferQueue(block,
Pawin Vongmasa36653902018-11-15 00:10:25 -08001117 outputIgbp,
1118 outputGeneration,
1119 &bqSlot);
1120 if (status != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001121 LOG(WARNING) << "queueToOutputSurface -- attaching failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001122 return INVALID_OPERATION;
1123 }
1124
1125 status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
1126 input, output);
1127 if (status != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001128 LOG(ERROR) << "queueToOutputSurface -- queueBuffer() failed "
1129 "on non-bufferqueue-based block. "
1130 "Error = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001131 return status;
1132 }
1133 return OK;
1134 }
1135
1136 mOutputBufferQueueMutex.lock();
1137 sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp;
1138 uint64_t outputBqId = mOutputBqId;
1139 uint32_t outputGeneration = mOutputGeneration;
1140 mOutputBufferQueueMutex.unlock();
1141
1142 if (!outputIgbp) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001143 LOG(VERBOSE) << "queueToOutputSurface -- output surface is null.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001144 return NO_INIT;
1145 }
1146
Sungtak Lee9b148812019-01-27 16:30:13 -08001147 if (bqId != outputBqId || generation != outputGeneration) {
1148 if (!holdBufferQueueBlock(block, mOutputIgbp, mOutputBqId, mOutputGeneration)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001149 LOG(ERROR) << "queueToOutputSurface -- migration failed.";
Sungtak Lee9b148812019-01-27 16:30:13 -08001150 return DEAD_OBJECT;
1151 }
1152 if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001153 LOG(ERROR) << "queueToOutputSurface -- corrupted bufferqueue assignment.";
Sungtak Lee9b148812019-01-27 16:30:13 -08001154 return UNKNOWN_ERROR;
1155 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001156 }
1157
1158 status_t status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
1159 input, output);
1160 if (status != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001161 LOG(DEBUG) << "queueToOutputSurface -- queueBuffer() failed "
1162 "on bufferqueue-based block. "
1163 "Error = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001164 return status;
1165 }
1166 if (!yieldBufferQueueBlock(block)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001167 LOG(DEBUG) << "queueToOutputSurface -- cannot yield "
1168 "bufferqueue-based block to the bufferqueue.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001169 return UNKNOWN_ERROR;
1170 }
1171 return OK;
1172}
1173
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001174c2_status_t Codec2Client::Component::connectToInputSurface(
1175 const std::shared_ptr<InputSurface>& inputSurface,
1176 std::shared_ptr<InputSurfaceConnection>* connection) {
1177 c2_status_t status;
1178 Return<void> transStatus = mBase->connectToInputSurface(
1179 inputSurface->mBase,
1180 [&status, connection](
1181 Status s, const sp<IInputSurfaceConnection>& c) {
1182 status = static_cast<c2_status_t>(s);
1183 if (status != C2_OK) {
1184 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1185 << status << ".";
1186 return;
1187 }
1188 *connection = std::make_shared<InputSurfaceConnection>(c);
1189 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001190 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001191 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001192 return C2_TRANSACTION_FAILED;
1193 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001194 return status;
1195}
1196
1197c2_status_t Codec2Client::Component::connectToOmxInputSurface(
1198 const sp<HGraphicBufferProducer>& producer,
1199 const sp<HGraphicBufferSource>& source,
1200 std::shared_ptr<InputSurfaceConnection>* connection) {
1201 c2_status_t status;
1202 Return<void> transStatus = mBase->connectToOmxInputSurface(
1203 producer, source,
1204 [&status, connection](
1205 Status s, const sp<IInputSurfaceConnection>& c) {
1206 status = static_cast<c2_status_t>(s);
1207 if (status != C2_OK) {
1208 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1209 << status << ".";
1210 return;
1211 }
1212 *connection = std::make_shared<InputSurfaceConnection>(c);
1213 });
1214 if (!transStatus.isOk()) {
1215 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1216 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001217 }
1218 return status;
1219}
1220
1221c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001222 Return<Status> transStatus = mBase->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001223 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001224 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001225 return C2_TRANSACTION_FAILED;
1226 }
1227 c2_status_t status =
1228 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1229 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001230 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1231 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001232 }
1233 return status;
1234}
1235
1236c2_status_t Codec2Client::Component::setDeathListener(
1237 const std::shared_ptr<Component>& component,
1238 const std::shared_ptr<Listener>& listener) {
1239
1240 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1241 std::weak_ptr<Component> component;
1242 std::weak_ptr<Listener> base;
1243
1244 virtual void serviceDied(
1245 uint64_t /* cookie */,
1246 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1247 ) override {
1248 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1249 listener->onDeath(component);
1250 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001251 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001252 }
1253 }
1254 };
1255
1256 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1257 deathRecipient->base = listener;
1258 deathRecipient->component = component;
1259
1260 component->mDeathRecipient = deathRecipient;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001261 Return<bool> transResult = component->mBase->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001262 component->mDeathRecipient, 0);
1263 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001264 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001265 return C2_TRANSACTION_FAILED;
1266 }
1267 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001268 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001269 return C2_CORRUPTED;
1270 }
1271 return C2_OK;
1272}
1273
1274// Codec2Client::InputSurface
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001275Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base)
1276 : Configurable{
1277 [base]() -> sp<IConfigurable> {
1278 Return<sp<IConfigurable>> transResult =
1279 base->getConfigurable();
1280 return transResult.isOk() ?
1281 static_cast<sp<IConfigurable>>(transResult) :
1282 nullptr;
1283 }()
1284 },
1285 mBase{base},
1286 mGraphicBufferProducer{new
Pawin Vongmasa36653902018-11-15 00:10:25 -08001287 ::android::hardware::graphics::bufferqueue::V1_0::utils::
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001288 H2BGraphicBufferProducer([base]() -> sp<HGraphicBufferProducer> {
1289 Return<sp<HGraphicBufferProducer>> transResult =
1290 base->getGraphicBufferProducer();
1291 return transResult.isOk() ?
1292 static_cast<sp<HGraphicBufferProducer>>(transResult) :
1293 nullptr;
1294 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001295}
1296
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001297sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08001298 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1299 return mGraphicBufferProducer;
1300}
1301
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001302sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001303 return mBase;
1304}
1305
1306// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08001307Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001308 const sp<IInputSurfaceConnection>& base)
1309 : Configurable{
1310 [base]() -> sp<IConfigurable> {
1311 Return<sp<IConfigurable>> transResult =
1312 base->getConfigurable();
1313 return transResult.isOk() ?
1314 static_cast<sp<IConfigurable>>(transResult) :
1315 nullptr;
1316 }()
1317 },
1318 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001319}
1320
1321c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001322 Return<Status> transResult = mBase->disconnect();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001323 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1324}
1325
1326} // namespace android
1327