blob: 0fe8376ba5ebaa097088a4e4b7c81e514cb29c05 [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>
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080032#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
33#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080034#include <hidl/HidlSupport.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;
Pawin Vongmasa36653902018-11-15 00:10:25 -080053
Pawin Vongmasad0f0e142018-11-15 03:36:28 -080054using namespace ::android::hardware::media::c2::V1_0;
55using namespace ::android::hardware::media::c2::V1_0::utils;
Sungtak Leed3318082018-09-07 15:52:43 -070056using namespace ::android::hardware::media::bufferpool::V2_0;
57using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
Pawin Vongmasa36653902018-11-15 00:10:25 -080058
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080059using HGraphicBufferProducer1 = ::android::hardware::graphics::bufferqueue::
60 V1_0::IGraphicBufferProducer;
61using HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
62 V2_0::IGraphicBufferProducer;
63using B2HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
64 V2_0::utils::B2HGraphicBufferProducer;
65using H2BGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
66 V2_0::utils::H2BGraphicBufferProducer;
67
Pawin Vongmasa36653902018-11-15 00:10:25 -080068namespace /* unnamed */ {
69
70// c2_status_t value that corresponds to hwbinder transaction failure.
71constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
72
73// List of known IComponentStore services in the decreasing order of preference.
74constexpr const char* kClientNames[] = {
75 "default",
76 "software",
77 };
78
79// Number of known IComponentStore services.
80constexpr size_t kNumClients = std::extent<decltype(kClientNames)>::value;
81
82typedef std::array<std::shared_ptr<Codec2Client>, kNumClients> ClientList;
83
84// Convenience methods to obtain known clients.
85std::shared_ptr<Codec2Client> getClient(size_t index) {
Pawin Vongmasae55ed3f2018-11-28 03:39:57 -080086 uint32_t serviceMask = ::android::base::GetUintProperty(
87 "debug.media.codec2", uint32_t(0));
88 return Codec2Client::CreateFromService(
89 kClientNames[index],
90 (serviceMask & (1 << index)) != 0);
Pawin Vongmasa36653902018-11-15 00:10:25 -080091}
92
93ClientList getClientList() {
94 ClientList list;
95 for (size_t i = 0; i < list.size(); ++i) {
96 list[i] = getClient(i);
97 }
98 return list;
99}
100
101} // unnamed
102
103// Codec2ConfigurableClient
104
105const C2String& Codec2ConfigurableClient::getName() const {
106 return mName;
107}
108
Pawin Vongmasa36653902018-11-15 00:10:25 -0800109Codec2ConfigurableClient::Codec2ConfigurableClient(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800110 const sp<IConfigurable>& base)
111 : mBase{base},
112 mName{[base]() -> C2String {
113 C2String outName;
114 Return<void> transStatus = base->getName(
115 [&outName](const hidl_string& name) {
116 outName = name.c_str();
117 });
118 return transStatus.isOk() ? outName : "";
119 }()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800120}
121
122c2_status_t Codec2ConfigurableClient::query(
123 const std::vector<C2Param*> &stackParams,
124 const std::vector<C2Param::Index> &heapParamIndices,
125 c2_blocking_t mayBlock,
126 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
127 hidl_vec<ParamIndex> indices(
128 stackParams.size() + heapParamIndices.size());
129 size_t numIndices = 0;
130 for (C2Param* const& stackParam : stackParams) {
131 if (!stackParam) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800132 LOG(WARNING) << "query -- null stack param encountered.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800133 continue;
134 }
135 indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
136 }
137 size_t numStackIndices = numIndices;
138 for (const C2Param::Index& index : heapParamIndices) {
139 indices[numIndices++] =
140 static_cast<ParamIndex>(static_cast<uint32_t>(index));
141 }
142 indices.resize(numIndices);
143 if (heapParams) {
144 heapParams->reserve(heapParams->size() + numIndices);
145 }
146 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800147 Return<void> transStatus = mBase->query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800148 indices,
149 mayBlock == C2_MAY_BLOCK,
150 [&status, &numStackIndices, &stackParams, heapParams](
151 Status s, const Params& p) {
152 status = static_cast<c2_status_t>(s);
153 if (status != C2_OK && status != C2_BAD_INDEX) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800154 LOG(DEBUG) << "query -- call failed: "
155 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800156 return;
157 }
158 std::vector<C2Param*> paramPointers;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800159 if (!parseParamsBlob(&paramPointers, p)) {
160 LOG(ERROR) << "query -- error while parsing params.";
161 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800162 return;
163 }
164 size_t i = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800165 for (auto it = paramPointers.begin();
166 it != paramPointers.end(); ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800167 C2Param* paramPointer = *it;
168 if (numStackIndices > 0) {
169 --numStackIndices;
170 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800171 LOG(WARNING) << "query -- null stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800172 ++it;
173 continue;
174 }
175 for (; i < stackParams.size() && !stackParams[i]; ) {
176 ++i;
177 }
178 if (i >= stackParams.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800179 LOG(ERROR) << "query -- unexpected error.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800180 status = C2_CORRUPTED;
181 return;
182 }
183 if (stackParams[i]->index() != paramPointer->index()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800184 LOG(WARNING) << "query -- param skipped: "
185 "index = "
186 << stackParams[i]->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800187 stackParams[i++]->invalidate();
188 continue;
189 }
190 if (!stackParams[i++]->updateFrom(*paramPointer)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800191 LOG(WARNING) << "query -- param update failed: "
192 "index = "
193 << paramPointer->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800194 }
195 } else {
196 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800197 LOG(WARNING) << "query -- null heap param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800198 ++it;
199 continue;
200 }
201 if (!heapParams) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800202 LOG(WARNING) << "query -- "
203 "unexpected extra stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800204 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800205 heapParams->emplace_back(
206 C2Param::Copy(*paramPointer));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800207 }
208 }
209 ++it;
210 }
211 });
212 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800213 LOG(ERROR) << "query -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800214 return C2_TRANSACTION_FAILED;
215 }
216 return status;
217}
218
219c2_status_t Codec2ConfigurableClient::config(
220 const std::vector<C2Param*> &params,
221 c2_blocking_t mayBlock,
222 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
223 Params hidlParams;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800224 if (!createParamsBlob(&hidlParams, params)) {
225 LOG(ERROR) << "config -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800226 return C2_TRANSACTION_FAILED;
227 }
228 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800229 Return<void> transStatus = mBase->config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800230 hidlParams,
231 mayBlock == C2_MAY_BLOCK,
232 [&status, &params, failures](
233 Status s,
234 const hidl_vec<SettingResult> f,
235 const Params& o) {
236 status = static_cast<c2_status_t>(s);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800237 if (status != C2_OK && status != C2_BAD_INDEX) {
238 LOG(DEBUG) << "config -- call failed: "
239 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800240 }
241 size_t i = failures->size();
242 failures->resize(i + f.size());
243 for (const SettingResult& sf : f) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800244 if (!objcpy(&(*failures)[i++], sf)) {
245 LOG(ERROR) << "config -- "
246 << "invalid SettingResult returned.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800247 return;
248 }
249 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800250 if (!updateParamsFromBlob(params, o)) {
251 LOG(ERROR) << "config -- "
252 << "failed to parse returned params.";
253 status = C2_CORRUPTED;
254 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800255 });
256 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800257 LOG(ERROR) << "config -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800258 return C2_TRANSACTION_FAILED;
259 }
260 return status;
261}
262
263c2_status_t Codec2ConfigurableClient::querySupportedParams(
264 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
265 // TODO: Cache and query properly!
266 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800267 Return<void> transStatus = mBase->querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800268 std::numeric_limits<uint32_t>::min(),
269 std::numeric_limits<uint32_t>::max(),
270 [&status, params](
271 Status s,
272 const hidl_vec<ParamDescriptor>& p) {
273 status = static_cast<c2_status_t>(s);
274 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800275 LOG(DEBUG) << "querySupportedParams -- call failed: "
276 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800277 return;
278 }
279 size_t i = params->size();
280 params->resize(i + p.size());
281 for (const ParamDescriptor& sp : p) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800282 if (!objcpy(&(*params)[i++], sp)) {
283 LOG(ERROR) << "querySupportedParams -- "
284 << "invalid returned ParamDescriptor.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800285 return;
286 }
287 }
288 });
289 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800290 LOG(ERROR) << "querySupportedParams -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800291 return C2_TRANSACTION_FAILED;
292 }
293 return status;
294}
295
296c2_status_t Codec2ConfigurableClient::querySupportedValues(
297 std::vector<C2FieldSupportedValuesQuery>& fields,
298 c2_blocking_t mayBlock) const {
299 hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
300 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800301 if (!objcpy(&inFields[i], fields[i])) {
302 LOG(ERROR) << "querySupportedValues -- bad input";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800303 return C2_TRANSACTION_FAILED;
304 }
305 }
306
307 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800308 Return<void> transStatus = mBase->querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800309 inFields,
310 mayBlock == C2_MAY_BLOCK,
311 [&status, &inFields, &fields](
312 Status s,
313 const hidl_vec<FieldSupportedValuesQueryResult>& r) {
314 status = static_cast<c2_status_t>(s);
315 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800316 LOG(DEBUG) << "querySupportedValues -- call failed: "
317 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800318 return;
319 }
320 if (r.size() != fields.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800321 LOG(ERROR) << "querySupportedValues -- "
322 "input and output lists "
323 "have different sizes.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800324 status = C2_CORRUPTED;
325 return;
326 }
327 for (size_t i = 0; i < fields.size(); ++i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800328 if (!objcpy(&fields[i], inFields[i], r[i])) {
329 LOG(ERROR) << "querySupportedValues -- "
330 "invalid returned value.";
331 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800332 return;
333 }
334 }
335 });
336 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800337 LOG(ERROR) << "querySupportedValues -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800338 return C2_TRANSACTION_FAILED;
339 }
340 return status;
341}
342
343// Codec2Client::Component::HidlListener
344struct Codec2Client::Component::HidlListener : public IComponentListener {
345 std::weak_ptr<Component> component;
346 std::weak_ptr<Listener> base;
347
348 virtual Return<void> onWorkDone(const WorkBundle& workBundle) override {
349 std::list<std::unique_ptr<C2Work>> workItems;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800350 if (!objcpy(&workItems, workBundle)) {
351 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800352 return Void();
353 }
354 // release input buffers potentially held by the component from queue
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800355 std::shared_ptr<Codec2Client::Component> strongComponent =
356 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800357 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800358 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800359 }
360 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800361 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800362 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800363 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800364 }
365 return Void();
366 }
367
368 virtual Return<void> onTripped(
369 const hidl_vec<SettingResult>& settingResults) override {
370 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
371 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800372 for (size_t i = 0; i < settingResults.size(); ++i) {
373 std::unique_ptr<C2SettingResult> c2SettingResult;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800374 if (!objcpy(&c2SettingResult, settingResults[i])) {
375 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800376 return Void();
377 }
378 c2SettingResults[i] = std::move(c2SettingResult);
379 }
380 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
381 listener->onTripped(component, c2SettingResults);
382 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800383 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800384 }
385 return Void();
386 }
387
388 virtual Return<void> onError(Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800389 LOG(DEBUG) << "onError --"
390 << " status = " << s
391 << ", errorCode = " << errorCode
392 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800393 if (std::shared_ptr<Listener> listener = base.lock()) {
394 listener->onError(component, s == Status::OK ?
395 errorCode : static_cast<c2_status_t>(s));
396 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800397 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800398 }
399 return Void();
400 }
401
402 virtual Return<void> onFramesRendered(
403 const hidl_vec<RenderedFrame>& renderedFrames) override {
404 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800405 if (!listener) {
406 LOG(DEBUG) << "onFramesRendered -- listener died.";
407 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800408 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800409 for (const RenderedFrame& renderedFrame : renderedFrames) {
410 listener->onFrameRendered(
411 renderedFrame.bufferQueueId,
412 renderedFrame.slotId,
413 renderedFrame.timestampNs);
414 }
415 return Void();
416 }
417
418 virtual Return<void> onInputBuffersReleased(
419 const hidl_vec<InputBuffer>& inputBuffers) override {
420 std::shared_ptr<Listener> listener = base.lock();
421 if (!listener) {
422 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
423 return Void();
424 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800425 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800426 LOG(VERBOSE) << "onInputBuffersReleased --"
427 " received death notification of"
428 " input buffer:"
429 " frameIndex = " << inputBuffer.frameIndex
430 << ", bufferIndex = " << inputBuffer.arrayIndex
431 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -0800432 listener->onInputBufferDone(
433 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800434 }
435 return Void();
436 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800437
Pawin Vongmasa36653902018-11-15 00:10:25 -0800438};
439
440// Codec2Client
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800441Codec2Client::Codec2Client(const sp<IComponentStore>& base,
442 std::string serviceName)
443 : Configurable{
444 [base]() -> sp<IConfigurable> {
445 Return<sp<IConfigurable>> transResult =
446 base->getConfigurable();
447 return transResult.isOk() ?
448 static_cast<sp<IConfigurable>>(transResult) :
449 nullptr;
450 }()
451 },
452 mBase{base},
453 mListed{false},
454 mServiceName{serviceName} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800455 Return<sp<IClientManager>> transResult = base->getPoolClientManager();
456 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800457 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800458 } else {
459 mHostPoolManager = static_cast<sp<IClientManager>>(transResult);
460 }
461}
462
463c2_status_t Codec2Client::createComponent(
464 const C2String& name,
465 const std::shared_ptr<Codec2Client::Listener>& listener,
466 std::shared_ptr<Codec2Client::Component>* const component) {
467
Pawin Vongmasa36653902018-11-15 00:10:25 -0800468 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800469 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800470 hidlListener->base = listener;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800471 Return<void> transStatus = mBase->createComponent(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800472 name,
473 hidlListener,
474 ClientManager::getInstance(),
475 [&status, component, hidlListener](
476 Status s,
477 const sp<IComponent>& c) {
478 status = static_cast<c2_status_t>(s);
479 if (status != C2_OK) {
480 return;
481 }
482 *component = std::make_shared<Codec2Client::Component>(c);
483 hidlListener->component = *component;
484 });
485 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800486 LOG(ERROR) << "createComponent(" << name.c_str()
487 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800488 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800489 } else if (status != C2_OK) {
490 LOG(ERROR) << "createComponent(" << name.c_str()
491 << ") -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800492 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800493 } else if (!*component) {
494 LOG(ERROR) << "createComponent(" << name.c_str()
495 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800496 return C2_CORRUPTED;
497 }
498
499 status = (*component)->setDeathListener(*component, listener);
500 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800501 LOG(ERROR) << "createComponent(" << name.c_str()
502 << ") -- failed to set up death listener: "
503 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800504 }
505
506 (*component)->mBufferPoolSender.setReceiver(mHostPoolManager);
507 return status;
508}
509
510c2_status_t Codec2Client::createInterface(
511 const C2String& name,
512 std::shared_ptr<Codec2Client::Interface>* const interface) {
513 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800514 Return<void> transStatus = mBase->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800515 name,
516 [&status, interface](
517 Status s,
518 const sp<IComponentInterface>& i) {
519 status = static_cast<c2_status_t>(s);
520 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800521 return;
522 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800523 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800524 });
525 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800526 LOG(ERROR) << "createInterface(" << name.c_str()
527 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800528 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800529 } else if (status != C2_OK) {
530 LOG(ERROR) << "createComponent(" << name.c_str()
531 << ") -- call failed: " << status << ".";
532 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800533 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800534
Pawin Vongmasa36653902018-11-15 00:10:25 -0800535 return status;
536}
537
538c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800539 std::shared_ptr<InputSurface>* const inputSurface) {
540 c2_status_t status;
541 Return<void> transStatus = mBase->createInputSurface(
542 [&status, inputSurface](
543 Status s,
544 const sp<IInputSurface>& i) {
545 status = static_cast<c2_status_t>(s);
546 if (status != C2_OK) {
547 return;
548 }
549 *inputSurface = std::make_shared<InputSurface>(i);
550 });
551 if (!transStatus.isOk()) {
552 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800553 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800554 } else if (status != C2_OK) {
555 LOG(DEBUG) << "createInputSurface -- call failed: "
556 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800557 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800558 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800559}
560
561const std::vector<C2Component::Traits>& Codec2Client::listComponents() const {
562 std::lock_guard<std::mutex> lock(mMutex);
563 if (mListed) {
564 return mTraitsList;
565 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800566 Return<void> transStatus = mBase->listComponents(
567 [this](Status s,
568 const hidl_vec<IComponentStore::ComponentTraits>& t) {
569 if (s != Status::OK) {
570 LOG(DEBUG) << "listComponents -- call failed: "
571 << static_cast<c2_status_t>(s) << ".";
572 return;
573 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800574 mTraitsList.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800575 for (size_t i = 0; i < t.size(); ++i) {
Lajos Molnar8b5c20c2019-01-31 16:15:08 -0800576 if (!objcpy(&mTraitsList[i], t[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800577 LOG(ERROR) << "listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800578 return;
579 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800580 mTraitsList[i].owner = mServiceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800581 }
582 });
583 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800584 LOG(ERROR) << "listComponents -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800585 }
586 mListed = true;
587 return mTraitsList;
588}
589
590c2_status_t Codec2Client::copyBuffer(
591 const std::shared_ptr<C2Buffer>& src,
592 const std::shared_ptr<C2Buffer>& dst) {
593 // TODO: Implement?
594 (void)src;
595 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800596 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800597 return C2_OMITTED;
598}
599
600std::shared_ptr<C2ParamReflector>
601 Codec2Client::getParamReflector() {
602 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
603 // should reflect the HAL API.
604 struct SimpleParamReflector : public C2ParamReflector {
605 virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
606 hidl_vec<ParamIndex> indices(1);
607 indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
608 std::unique_ptr<C2StructDescriptor> descriptor;
609 Return<void> transStatus = mBase->getStructDescriptors(
610 indices,
611 [&descriptor](
612 Status s,
613 const hidl_vec<StructDescriptor>& sd) {
614 c2_status_t status = static_cast<c2_status_t>(s);
615 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800616 LOG(DEBUG) << "SimpleParamReflector -- "
617 "getStructDescriptors() failed: "
618 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800619 descriptor.reset();
620 return;
621 }
622 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800623 LOG(DEBUG) << "SimpleParamReflector -- "
624 "getStructDescriptors() "
625 "returned vector of size "
626 << sd.size() << ". "
627 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800628 descriptor.reset();
629 return;
630 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800631 if (!objcpy(&descriptor, sd[0])) {
632 LOG(DEBUG) << "SimpleParamReflector -- "
633 "getStructDescriptors() returned "
634 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800635 descriptor.reset();
636 return;
637 }
638 });
639 return descriptor;
640 }
641
642 SimpleParamReflector(sp<Base> base)
643 : mBase(base) { }
644
645 sp<Base> mBase;
646 };
647
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800648 return std::make_shared<SimpleParamReflector>(mBase);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800649};
650
651std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800652 const char* serviceName, bool waitForService) {
653 if (!serviceName) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800654 return nullptr;
655 }
656 sp<Base> baseStore = waitForService ?
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800657 Base::getService(serviceName) :
658 Base::tryGetService(serviceName);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800659 if (!baseStore) {
660 if (waitForService) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800661 LOG(WARNING) << "Codec2.0 service \"" << serviceName << "\""
662 " inaccessible. Check the device manifest.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800663 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800664 LOG(DEBUG) << "Codec2.0 service \"" << serviceName << "\""
665 " unavailable at the moment. "
666 " Wait or check the device manifest.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800667 }
668 return nullptr;
669 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800670 return std::make_shared<Codec2Client>(baseStore, serviceName);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800671}
672
673c2_status_t Codec2Client::ForAllStores(
674 const std::string &key,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800675 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
676 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800677 c2_status_t status = C2_NO_INIT; // no IComponentStores present
678
679 // Cache the mapping key -> index of Codec2Client in getClient().
680 static std::mutex key2IndexMutex;
681 static std::map<std::string, size_t> key2Index;
682
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800683 // By default try all stores. However, try the last known client first. If
684 // the last known client fails, retry once. We do this by pushing the last
685 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800686 std::deque<size_t> indices;
687 for (size_t index = kNumClients; index > 0; ) {
688 indices.push_front(--index);
689 }
690
691 bool wasMapped = false;
692 std::unique_lock<std::mutex> lock(key2IndexMutex);
693 auto it = key2Index.find(key);
694 if (it != key2Index.end()) {
695 indices.push_front(it->second);
696 wasMapped = true;
697 }
698 lock.unlock();
699
700 for (size_t index : indices) {
701 std::shared_ptr<Codec2Client> client = getClient(index);
702 if (client) {
703 status = predicate(client);
704 if (status == C2_OK) {
705 lock.lock();
706 key2Index[key] = index; // update last known client index
707 return status;
708 }
709 }
710 if (wasMapped) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800711 LOG(INFO) << "Could not find \"" << key << "\""
712 " in the last instance. Retrying...";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800713 wasMapped = false;
714 }
715 }
716 return status; // return the last status from a valid client
717}
718
719std::shared_ptr<Codec2Client::Component>
720 Codec2Client::CreateComponentByName(
721 const char* componentName,
722 const std::shared_ptr<Listener>& listener,
723 std::shared_ptr<Codec2Client>* owner) {
724 std::shared_ptr<Component> component;
725 c2_status_t status = ForAllStores(
726 componentName,
727 [owner, &component, componentName, &listener](
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800728 const std::shared_ptr<Codec2Client> &client)
729 -> c2_status_t {
730 c2_status_t status = client->createComponent(componentName,
731 listener,
732 &component);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800733 if (status == C2_OK) {
734 if (owner) {
735 *owner = client;
736 }
737 } else if (status != C2_NOT_FOUND) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800738 LOG(DEBUG) << "IComponentStore("
739 << client->getServiceName()
740 << ")::createComponent(\"" << componentName
741 << "\") returned status = "
742 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800743 }
744 return status;
745 });
746 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800747 LOG(DEBUG) << "Could not create component \"" << componentName << "\". "
748 "Status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800749 }
750 return component;
751}
752
753std::shared_ptr<Codec2Client::Interface>
754 Codec2Client::CreateInterfaceByName(
755 const char* interfaceName,
756 std::shared_ptr<Codec2Client>* owner) {
757 std::shared_ptr<Interface> interface;
758 c2_status_t status = ForAllStores(
759 interfaceName,
760 [owner, &interface, interfaceName](
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800761 const std::shared_ptr<Codec2Client> &client)
762 -> c2_status_t {
763 c2_status_t status = client->createInterface(interfaceName,
764 &interface);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800765 if (status == C2_OK) {
766 if (owner) {
767 *owner = client;
768 }
769 } else if (status != C2_NOT_FOUND) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800770 LOG(DEBUG) << "IComponentStore("
771 << client->getServiceName()
772 << ")::createInterface(\"" << interfaceName
773 << "\") returned status = "
774 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800775 }
776 return status;
777 });
778 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800779 LOG(DEBUG) << "Could not create interface \"" << interfaceName << "\". "
780 "Status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800781 }
782 return interface;
783}
784
785std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface() {
786 uint32_t serviceMask = ::android::base::GetUintProperty(
787 "debug.stagefright.c2inputsurface", uint32_t(0));
788 for (size_t i = 0; i < kNumClients; ++i) {
789 if ((1 << i) & serviceMask) {
790 std::shared_ptr<Codec2Client> client = getClient(i);
791 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
792 if (client &&
793 client->createInputSurface(&inputSurface) == C2_OK &&
794 inputSurface) {
795 return inputSurface;
796 }
797 }
798 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800799 LOG(INFO) << "Could not create an input surface "
800 "from any Codec2.0 services.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800801 return nullptr;
802}
803
804const std::vector<C2Component::Traits>& Codec2Client::ListComponents() {
805 static std::vector<C2Component::Traits> traitsList = [](){
806 std::vector<C2Component::Traits> list;
807 size_t listSize = 0;
808 ClientList clientList = getClientList();
809 for (const std::shared_ptr<Codec2Client>& client : clientList) {
810 if (!client) {
811 continue;
812 }
813 listSize += client->listComponents().size();
814 }
815 list.reserve(listSize);
816 for (const std::shared_ptr<Codec2Client>& client : clientList) {
817 if (!client) {
818 continue;
819 }
820 list.insert(
821 list.end(),
822 client->listComponents().begin(),
823 client->listComponents().end());
824 }
825 return list;
826 }();
827
828 return traitsList;
829}
830
831// Codec2Client::Listener
832
833Codec2Client::Listener::~Listener() {
834}
835
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800836// Codec2Client::Interface
837Codec2Client::Interface::Interface(const sp<Base>& base)
838 : Configurable{
839 [base]() -> sp<IConfigurable> {
840 Return<sp<IConfigurable>> transResult =
841 base->getConfigurable();
842 return transResult.isOk() ?
843 static_cast<sp<IConfigurable>>(transResult) :
844 nullptr;
845 }()
846 },
847 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800848}
849
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800850// Codec2Client::Component
851Codec2Client::Component::Component(const sp<Base>& base)
852 : Configurable{
853 [base]() -> sp<IConfigurable> {
854 Return<sp<IComponentInterface>> transResult1 =
855 base->getInterface();
856 if (!transResult1.isOk()) {
857 return nullptr;
858 }
859 Return<sp<IConfigurable>> transResult2 =
860 static_cast<sp<IComponentInterface>>(transResult1)->
861 getConfigurable();
862 return transResult2.isOk() ?
863 static_cast<sp<IConfigurable>>(transResult2) :
864 nullptr;
865 }()
866 },
867 mBase{base},
868 mBufferPoolSender{nullptr} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800869}
870
871Codec2Client::Component::~Component() {
872}
873
874c2_status_t Codec2Client::Component::createBlockPool(
875 C2Allocator::id_t id,
876 C2BlockPool::local_id_t* blockPoolId,
877 std::shared_ptr<Codec2Client::Configurable>* configurable) {
878 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800879 Return<void> transStatus = mBase->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800880 static_cast<uint32_t>(id),
881 [&status, blockPoolId, configurable](
882 Status s,
883 uint64_t pId,
884 const sp<IConfigurable>& c) {
885 status = static_cast<c2_status_t>(s);
886 configurable->reset();
887 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800888 LOG(DEBUG) << "createBlockPool -- call failed: "
889 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800890 return;
891 }
892 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800893 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800894 });
895 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800896 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800897 return C2_TRANSACTION_FAILED;
898 }
899 return status;
900}
901
902c2_status_t Codec2Client::Component::destroyBlockPool(
903 C2BlockPool::local_id_t localId) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800904 Return<Status> transResult = mBase->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800905 static_cast<uint64_t>(localId));
906 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800907 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800908 return C2_TRANSACTION_FAILED;
909 }
910 return static_cast<c2_status_t>(static_cast<Status>(transResult));
911}
912
Wonsik Kimab34ed62019-01-31 15:28:46 -0800913void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800914 const std::list<std::unique_ptr<C2Work>> &workItems) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800915 // Output bufferqueue-based blocks' lifetime management
916 mOutputBufferQueueMutex.lock();
917 sp<IGraphicBufferProducer> igbp = mOutputIgbp;
918 uint64_t bqId = mOutputBqId;
919 uint32_t generation = mOutputGeneration;
920 mOutputBufferQueueMutex.unlock();
921
922 if (igbp) {
923 holdBufferQueueBlocks(workItems, igbp, bqId, generation);
924 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800925}
926
927c2_status_t Codec2Client::Component::queue(
928 std::list<std::unique_ptr<C2Work>>* const items) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800929 WorkBundle workBundle;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800930 if (!objcpy(&workBundle, *items, &mBufferPoolSender)) {
931 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800932 return C2_TRANSACTION_FAILED;
933 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800934 Return<Status> transStatus = mBase->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800935 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800936 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800937 return C2_TRANSACTION_FAILED;
938 }
939 c2_status_t status =
940 static_cast<c2_status_t>(static_cast<Status>(transStatus));
941 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800942 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800943 }
944 return status;
945}
946
947c2_status_t Codec2Client::Component::flush(
948 C2Component::flush_mode_t mode,
949 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
950 (void)mode; // Flush mode isn't supported in HIDL yet.
951 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800952 Return<void> transStatus = mBase->flush(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800953 [&status, flushedWork](
954 Status s, const WorkBundle& wb) {
955 status = static_cast<c2_status_t>(s);
956 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800957 LOG(DEBUG) << "flush -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800958 return;
959 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800960 if (!objcpy(flushedWork, wb)) {
961 status = C2_CORRUPTED;
962 } else {
963 status = C2_OK;
964 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800965 });
966 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800967 LOG(ERROR) << "flush -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800968 return C2_TRANSACTION_FAILED;
969 }
970
971 // Indices of flushed work items.
972 std::vector<uint64_t> flushedIndices;
973 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
974 if (work) {
975 if (work->worklets.empty()
976 || !work->worklets.back()
977 || (work->worklets.back()->output.flags &
978 C2FrameData::FLAG_INCOMPLETE) == 0) {
979 // input is complete
980 flushedIndices.emplace_back(
981 work->input.ordinal.frameIndex.peeku());
982 }
983 }
984 }
985
Pawin Vongmasa36653902018-11-15 00:10:25 -0800986 // Output bufferqueue-based blocks' lifetime management
987 mOutputBufferQueueMutex.lock();
988 sp<IGraphicBufferProducer> igbp = mOutputIgbp;
989 uint64_t bqId = mOutputBqId;
990 uint32_t generation = mOutputGeneration;
991 mOutputBufferQueueMutex.unlock();
992
993 if (igbp) {
994 holdBufferQueueBlocks(*flushedWork, igbp, bqId, generation);
995 }
996
997 return status;
998}
999
1000c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001001 Return<Status> transStatus = mBase->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001002 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
1003 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001004 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001005 return C2_TRANSACTION_FAILED;
1006 }
1007 c2_status_t status =
1008 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1009 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001010 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001011 }
1012 return status;
1013}
1014
1015c2_status_t Codec2Client::Component::start() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001016 Return<Status> transStatus = mBase->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001017 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001018 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001019 return C2_TRANSACTION_FAILED;
1020 }
1021 c2_status_t status =
1022 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1023 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001024 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001025 }
1026 return status;
1027}
1028
1029c2_status_t Codec2Client::Component::stop() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001030 Return<Status> transStatus = mBase->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001031 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001032 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001033 return C2_TRANSACTION_FAILED;
1034 }
1035 c2_status_t status =
1036 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1037 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001038 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001039 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001040 return status;
1041}
1042
1043c2_status_t Codec2Client::Component::reset() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001044 Return<Status> transStatus = mBase->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001045 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001046 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001047 return C2_TRANSACTION_FAILED;
1048 }
1049 c2_status_t status =
1050 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1051 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001052 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001053 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001054 return status;
1055}
1056
1057c2_status_t Codec2Client::Component::release() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001058 Return<Status> transStatus = mBase->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001059 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001060 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001061 return C2_TRANSACTION_FAILED;
1062 }
1063 c2_status_t status =
1064 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1065 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001066 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001067 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001068 return status;
1069}
1070
1071c2_status_t Codec2Client::Component::setOutputSurface(
1072 C2BlockPool::local_id_t blockPoolId,
1073 const sp<IGraphicBufferProducer>& surface,
1074 uint32_t generation) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001075 sp<HGraphicBufferProducer2> igbp =
1076 surface->getHalInterface<HGraphicBufferProducer2>();
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08001077
Pawin Vongmasa36653902018-11-15 00:10:25 -08001078 if (!igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001079 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001080 }
1081
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001082 Return<Status> transStatus = mBase->setOutputSurface(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001083 static_cast<uint64_t>(blockPoolId), igbp);
1084 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001085 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001086 return C2_TRANSACTION_FAILED;
1087 }
1088 c2_status_t status =
1089 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1090 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001091 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001092 } else {
1093 std::lock_guard<std::mutex> lock(mOutputBufferQueueMutex);
1094 if (mOutputIgbp != surface) {
1095 mOutputIgbp = surface;
1096 if (!surface) {
1097 mOutputBqId = 0;
1098 } else if (surface->getUniqueId(&mOutputBqId) != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001099 LOG(ERROR) << "setOutputSurface -- "
1100 "cannot obtain bufferqueue id.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001101 }
1102 }
1103 mOutputGeneration = generation;
1104 }
1105 return status;
1106}
1107
1108status_t Codec2Client::Component::queueToOutputSurface(
1109 const C2ConstGraphicBlock& block,
1110 const QueueBufferInput& input,
1111 QueueBufferOutput* output) {
1112 uint32_t generation;
1113 uint64_t bqId;
1114 int32_t bqSlot;
1115 if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot) ||
1116 bqId == 0) {
1117 // Block not from bufferqueue -- it must be attached before queuing.
1118
1119 mOutputBufferQueueMutex.lock();
1120 sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp;
1121 uint32_t outputGeneration = mOutputGeneration;
1122 mOutputBufferQueueMutex.unlock();
1123
Sungtak Lee9b148812019-01-27 16:30:13 -08001124 status_t status = attachToBufferQueue(block,
Pawin Vongmasa36653902018-11-15 00:10:25 -08001125 outputIgbp,
1126 outputGeneration,
1127 &bqSlot);
1128 if (status != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001129 LOG(WARNING) << "queueToOutputSurface -- attaching failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001130 return INVALID_OPERATION;
1131 }
1132
1133 status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
1134 input, output);
1135 if (status != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001136 LOG(ERROR) << "queueToOutputSurface -- queueBuffer() failed "
1137 "on non-bufferqueue-based block. "
1138 "Error = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001139 return status;
1140 }
1141 return OK;
1142 }
1143
1144 mOutputBufferQueueMutex.lock();
1145 sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp;
1146 uint64_t outputBqId = mOutputBqId;
1147 uint32_t outputGeneration = mOutputGeneration;
1148 mOutputBufferQueueMutex.unlock();
1149
1150 if (!outputIgbp) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001151 LOG(VERBOSE) << "queueToOutputSurface -- output surface is null.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001152 return NO_INIT;
1153 }
1154
Sungtak Lee9b148812019-01-27 16:30:13 -08001155 if (bqId != outputBqId || generation != outputGeneration) {
1156 if (!holdBufferQueueBlock(block, mOutputIgbp, mOutputBqId, mOutputGeneration)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001157 LOG(ERROR) << "queueToOutputSurface -- migration failed.";
Sungtak Lee9b148812019-01-27 16:30:13 -08001158 return DEAD_OBJECT;
1159 }
1160 if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001161 LOG(ERROR) << "queueToOutputSurface -- corrupted bufferqueue assignment.";
Sungtak Lee9b148812019-01-27 16:30:13 -08001162 return UNKNOWN_ERROR;
1163 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001164 }
1165
1166 status_t status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
1167 input, output);
1168 if (status != OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001169 LOG(DEBUG) << "queueToOutputSurface -- queueBuffer() failed "
1170 "on bufferqueue-based block. "
1171 "Error = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001172 return status;
1173 }
1174 if (!yieldBufferQueueBlock(block)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001175 LOG(DEBUG) << "queueToOutputSurface -- cannot yield "
1176 "bufferqueue-based block to the bufferqueue.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001177 return UNKNOWN_ERROR;
1178 }
1179 return OK;
1180}
1181
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001182c2_status_t Codec2Client::Component::connectToInputSurface(
1183 const std::shared_ptr<InputSurface>& inputSurface,
1184 std::shared_ptr<InputSurfaceConnection>* connection) {
1185 c2_status_t status;
1186 Return<void> transStatus = mBase->connectToInputSurface(
1187 inputSurface->mBase,
1188 [&status, connection](
1189 Status s, const sp<IInputSurfaceConnection>& c) {
1190 status = static_cast<c2_status_t>(s);
1191 if (status != C2_OK) {
1192 LOG(DEBUG) << "connectToInputSurface -- call failed: "
1193 << status << ".";
1194 return;
1195 }
1196 *connection = std::make_shared<InputSurfaceConnection>(c);
1197 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08001198 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001199 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001200 return C2_TRANSACTION_FAILED;
1201 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001202 return status;
1203}
1204
1205c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001206 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001207 const sp<HGraphicBufferSource>& source,
1208 std::shared_ptr<InputSurfaceConnection>* connection) {
1209 c2_status_t status;
1210 Return<void> transStatus = mBase->connectToOmxInputSurface(
1211 producer, source,
1212 [&status, connection](
1213 Status s, const sp<IInputSurfaceConnection>& c) {
1214 status = static_cast<c2_status_t>(s);
1215 if (status != C2_OK) {
1216 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
1217 << status << ".";
1218 return;
1219 }
1220 *connection = std::make_shared<InputSurfaceConnection>(c);
1221 });
1222 if (!transStatus.isOk()) {
1223 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
1224 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001225 }
1226 return status;
1227}
1228
1229c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001230 Return<Status> transStatus = mBase->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001231 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001232 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001233 return C2_TRANSACTION_FAILED;
1234 }
1235 c2_status_t status =
1236 static_cast<c2_status_t>(static_cast<Status>(transStatus));
1237 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001238 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
1239 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001240 }
1241 return status;
1242}
1243
1244c2_status_t Codec2Client::Component::setDeathListener(
1245 const std::shared_ptr<Component>& component,
1246 const std::shared_ptr<Listener>& listener) {
1247
1248 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
1249 std::weak_ptr<Component> component;
1250 std::weak_ptr<Listener> base;
1251
1252 virtual void serviceDied(
1253 uint64_t /* cookie */,
1254 const wp<::android::hidl::base::V1_0::IBase>& /* who */
1255 ) override {
1256 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1257 listener->onDeath(component);
1258 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001259 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001260 }
1261 }
1262 };
1263
1264 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
1265 deathRecipient->base = listener;
1266 deathRecipient->component = component;
1267
1268 component->mDeathRecipient = deathRecipient;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001269 Return<bool> transResult = component->mBase->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001270 component->mDeathRecipient, 0);
1271 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001272 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001273 return C2_TRANSACTION_FAILED;
1274 }
1275 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001276 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001277 return C2_CORRUPTED;
1278 }
1279 return C2_OK;
1280}
1281
1282// Codec2Client::InputSurface
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001283Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base)
1284 : Configurable{
1285 [base]() -> sp<IConfigurable> {
1286 Return<sp<IConfigurable>> transResult =
1287 base->getConfigurable();
1288 return transResult.isOk() ?
1289 static_cast<sp<IConfigurable>>(transResult) :
1290 nullptr;
1291 }()
1292 },
1293 mBase{base},
1294 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001295 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
1296 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001297 base->getGraphicBufferProducer();
1298 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08001299 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001300 nullptr;
1301 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001302}
1303
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001304sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08001305 Codec2Client::InputSurface::getGraphicBufferProducer() const {
1306 return mGraphicBufferProducer;
1307}
1308
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001309sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001310 return mBase;
1311}
1312
1313// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08001314Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001315 const sp<IInputSurfaceConnection>& base)
1316 : Configurable{
1317 [base]() -> sp<IConfigurable> {
1318 Return<sp<IConfigurable>> transResult =
1319 base->getConfigurable();
1320 return transResult.isOk() ?
1321 static_cast<sp<IConfigurable>>(transResult) :
1322 nullptr;
1323 }()
1324 },
1325 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001326}
1327
1328c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001329 Return<Status> transResult = mBase->disconnect();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001330 return static_cast<c2_status_t>(static_cast<Status>(transResult));
1331}
1332
1333} // namespace android
1334