1 /*
2 * Copyright 2018 The Android Open Source Project
3 *
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 "Codec2-types"
19 #include <android-base/logging.h>
20
21 #include <bufferpool/ClientManager.h>
22 #include <codec2/common/BufferTypes.h>
23 #include <codec2/common/ParamTypes.h>
24 #include <codec2/hidl/1.0/types.h>
25
26 #include <C2AllocatorIon.h>
27 #include <C2AllocatorGralloc.h>
28 #include <C2BlockInternal.h>
29 #include <C2Buffer.h>
30 #include <C2Component.h>
31 #include <C2FenceFactory.h>
32 #include <C2PlatformSupport.h>
33 #include <C2Work.h>
34
35 namespace android {
36
37 using hardware::media::bufferpool::V2_0::implementation::ClientManager;
38 using hardware::media::c2::V1_0::BaseBlock;
39 using hardware::media::c2::V1_0::FieldSupportedValues;
40 using hardware::media::c2::V1_0::PrimitiveValue;
41 using hardware::media::c2::V1_0::ValueRange;
42 using hardware::media::c2::V1_0::utils::BufferPoolTypes;
43 using hardware::hidl_vec;
44
45 // C2FieldSupportedValues -> FieldSupportedValues
46 template<>
objcpy(FieldSupportedValues * d,const C2FieldSupportedValues & s)47 bool objcpy(
48 FieldSupportedValues *d, const C2FieldSupportedValues &s) {
49 switch (s.type) {
50 case C2FieldSupportedValues::EMPTY: {
51 d->empty(::android::hidl::safe_union::V1_0::Monostate{});
52 break;
53 }
54 case C2FieldSupportedValues::RANGE: {
55 ValueRange range{};
56 if (!objcpy(&range, s.range)) {
57 LOG(ERROR) << "Invalid C2FieldSupportedValues::range.";
58 d->range(range);
59 return false;
60 }
61 d->range(range);
62 break;
63 }
64 case C2FieldSupportedValues::VALUES: {
65 hidl_vec<PrimitiveValue> values;
66 copyVector<uint64_t>(&values, s.values);
67 d->values(values);
68 break;
69 }
70 case C2FieldSupportedValues::FLAGS: {
71 hidl_vec<PrimitiveValue> flags;
72 copyVector<uint64_t>(&flags, s.values);
73 d->flags(flags);
74 break;
75 }
76 default:
77 LOG(DEBUG) << "Unrecognized C2FieldSupportedValues::type_t "
78 << "with underlying value " << underlying_value(s.type)
79 << ".";
80 return false;
81 }
82 return true;
83 }
84
85 // FieldSupportedValues -> C2FieldSupportedValues
86 template<>
objcpy(C2FieldSupportedValues * d,const FieldSupportedValues & s)87 bool objcpy(
88 C2FieldSupportedValues *d, const FieldSupportedValues &s) {
89 switch (s.getDiscriminator()) {
90 case FieldSupportedValues::hidl_discriminator::empty: {
91 d->type = C2FieldSupportedValues::EMPTY;
92 break;
93 }
94 case FieldSupportedValues::hidl_discriminator::range: {
95 d->type = C2FieldSupportedValues::RANGE;
96 if (!objcpy(&d->range, s.range())) {
97 LOG(ERROR) << "Invalid FieldSupportedValues::range.";
98 return false;
99 }
100 d->values.resize(0);
101 break;
102 }
103 case FieldSupportedValues::hidl_discriminator::values: {
104 d->type = C2FieldSupportedValues::VALUES;
105 copyVector<uint64_t>(&d->values, s.values());
106 break;
107 }
108 case FieldSupportedValues::hidl_discriminator::flags: {
109 d->type = C2FieldSupportedValues::FLAGS;
110 copyVector<uint64_t>(&d->values, s.flags());
111 break;
112 }
113 default:
114 LOG(WARNING) << "Unrecognized FieldSupportedValues::getDiscriminator()";
115 return false;
116 }
117 return true;
118 }
119
120 template<>
objcpy(C2BaseBlock * d,const BaseBlock & s)121 bool objcpy(C2BaseBlock* d, const BaseBlock& s) {
122 switch (s.getDiscriminator()) {
123 case BaseBlock::hidl_discriminator::nativeBlock: {
124 if (s.nativeBlock() == nullptr) {
125 LOG(ERROR) << "Null BaseBlock::nativeBlock handle";
126 return false;
127 }
128 native_handle_t* sHandle =
129 native_handle_clone(s.nativeBlock());
130 if (sHandle == nullptr) {
131 LOG(ERROR) << "Null BaseBlock::nativeBlock.";
132 return false;
133 }
134 const C2Handle *sC2Handle =
135 reinterpret_cast<const C2Handle*>(sHandle);
136
137 d->linear = _C2BlockFactory::CreateLinearBlock(sC2Handle);
138 if (d->linear) {
139 d->type = C2BaseBlock::LINEAR;
140 return true;
141 }
142
143 d->graphic = _C2BlockFactory::CreateGraphicBlock(sC2Handle);
144 if (d->graphic) {
145 d->type = C2BaseBlock::GRAPHIC;
146 return true;
147 }
148
149 LOG(ERROR) << "Unknown handle type in BaseBlock::nativeBlock.";
150 if (sHandle) {
151 native_handle_close(sHandle);
152 native_handle_delete(sHandle);
153 }
154 return false;
155 }
156 case BaseBlock::hidl_discriminator::pooledBlock: {
157 const BufferPoolTypes::BufferStatusMessage &bpMessage =
158 s.pooledBlock();
159 sp<ClientManager> bp = ClientManager::getInstance();
160 std::shared_ptr<BufferPoolTypes::BufferPoolData> bpData;
161 native_handle_t *cHandle;
162 BufferPoolTypes::BufferPoolStatus bpStatus = bp->receive(
163 bpMessage.connectionId,
164 bpMessage.transactionId,
165 bpMessage.bufferId,
166 bpMessage.timestampUs,
167 &cHandle,
168 &bpData);
169 if (bpStatus != BufferPoolTypes::ResultStatus::OK) {
170 LOG(ERROR) << "Failed to receive buffer from bufferpool -- "
171 << "resultStatus = " << underlying_value(bpStatus)
172 << ".";
173 return false;
174 } else if (!bpData) {
175 LOG(ERROR) << "No data in bufferpool transaction.";
176 return false;
177 }
178
179 d->linear = _C2BlockFactory::CreateLinearBlock(cHandle, bpData);
180 if (d->linear) {
181 d->type = C2BaseBlock::LINEAR;
182 return true;
183 }
184
185 d->graphic = _C2BlockFactory::CreateGraphicBlock(cHandle, bpData);
186 if (d->graphic) {
187 d->type = C2BaseBlock::GRAPHIC;
188 return true;
189 }
190 if (cHandle) {
191 // Though we got cloned handle, creating block failed.
192 native_handle_close(cHandle);
193 native_handle_delete(cHandle);
194 }
195
196 LOG(ERROR) << "Unknown handle type in BaseBlock::pooledBlock.";
197 return false;
198 }
199 default:
200 LOG(ERROR) << "Unrecognized BaseBlock's discriminator with "
201 << "underlying value "
202 << underlying_value(s.getDiscriminator()) << ".";
203 return false;
204 }
205 }
206
207 template<>
SetHandle(BaseBlock * block,const C2Handle * handle)208 void SetHandle(BaseBlock *block, const C2Handle *handle) {
209 block->nativeBlock(reinterpret_cast<const native_handle_t*>(handle));
210 }
211
212 template<>
SetAHardwareBuffer(BaseBlock * block,AHardwareBuffer * pBuf)213 void SetAHardwareBuffer(BaseBlock *block, AHardwareBuffer *pBuf) {
214 (void) block;
215 (void) pBuf;
216 LOG(FATAL) << "This is not used";
217 }
218
219 template<>
SetPooledBlock(BaseBlock * baseBlock,const typename BufferPoolTypes::BufferStatusMessage & pooledBlock)220 void SetPooledBlock<BufferPoolTypes>(
221 BaseBlock *baseBlock,
222 const typename BufferPoolTypes::BufferStatusMessage &pooledBlock) {
223 baseBlock->pooledBlock(pooledBlock);
224 }
225
226 template<>
GetBufferPoolData(const std::shared_ptr<const _C2BlockPoolData> & blockPoolData,std::shared_ptr<typename BufferPoolTypes::BufferPoolData> * bpData)227 bool GetBufferPoolData<BufferPoolTypes>(
228 const std::shared_ptr<const _C2BlockPoolData>& blockPoolData,
229 std::shared_ptr<typename BufferPoolTypes::BufferPoolData> *bpData) {
230 return _C2BlockFactory::GetBufferPoolData(blockPoolData, bpData);
231 }
232
233 namespace hardware {
234 namespace media {
235 namespace c2 {
236 namespace V1_0 {
237 namespace utils {
238
239 using ::android::hardware::media::bufferpool::BufferPoolData;
240 using ::android::hardware::media::bufferpool::V2_0::ResultStatus;
241 using ::android::hardware::media::bufferpool::V2_0::implementation::
242 TransactionId;
243
asString(Status status,const char * def)244 const char* asString(Status status, const char* def) {
245 return asString(static_cast<c2_status_t>(status), def);
246 }
247
248 // C2FieldSupportedValuesQuery -> FieldSupportedValuesQuery
objcpy(FieldSupportedValuesQuery * d,const C2FieldSupportedValuesQuery & s)249 bool objcpy(
250 FieldSupportedValuesQuery* d,
251 const C2FieldSupportedValuesQuery& s) {
252 return ::android::objcpy(d, nullptr, s);
253 }
254
255 // FieldSupportedValuesQuery -> C2FieldSupportedValuesQuery
objcpy(C2FieldSupportedValuesQuery * d,const FieldSupportedValuesQuery & s)256 bool objcpy(
257 C2FieldSupportedValuesQuery* d,
258 const FieldSupportedValuesQuery& s) {
259 return ::android::objcpy(d, s);
260 }
261
262 // C2FieldSupportedValuesQuery -> FieldSupportedValuesQueryResult
objcpy(FieldSupportedValuesQueryResult * d,const C2FieldSupportedValuesQuery & s)263 bool objcpy(
264 FieldSupportedValuesQueryResult* d,
265 const C2FieldSupportedValuesQuery& s) {
266 return ::android::objcpy(nullptr, d, s);
267 }
268
269 // FieldSupportedValuesQuery, FieldSupportedValuesQueryResult ->
270 // C2FieldSupportedValuesQuery
objcpy(C2FieldSupportedValuesQuery * d,const FieldSupportedValuesQuery & sq,const FieldSupportedValuesQueryResult & sr)271 bool objcpy(
272 C2FieldSupportedValuesQuery* d,
273 const FieldSupportedValuesQuery& sq,
274 const FieldSupportedValuesQueryResult& sr) {
275 return ::android::objcpy(d, sq, sr);
276 }
277
278 // C2Component::Traits -> IComponentStore::ComponentTraits
objcpy(IComponentStore::ComponentTraits * d,const C2Component::Traits & s)279 bool objcpy(
280 IComponentStore::ComponentTraits *d,
281 const C2Component::Traits &s) {
282 return ::android::objcpy(d, s);
283 }
284
285 // ComponentTraits -> C2Component::Traits, std::unique_ptr<std::vector<std::string>>
objcpy(C2Component::Traits * d,const IComponentStore::ComponentTraits & s)286 bool objcpy(
287 C2Component::Traits* d,
288 const IComponentStore::ComponentTraits& s) {
289 return ::android::objcpy(d, s);
290 }
291
292 // C2SettingResult -> SettingResult
objcpy(SettingResult * d,const C2SettingResult & s)293 bool objcpy(SettingResult *d, const C2SettingResult &s) {
294 return ::android::objcpy(d, s);
295 }
296
297 // SettingResult -> std::unique_ptr<C2SettingResult>
objcpy(std::unique_ptr<C2SettingResult> * d,const SettingResult & s)298 bool objcpy(std::unique_ptr<C2SettingResult> *d, const SettingResult &s) {
299 return ::android::objcpy(d, s);
300 }
301
302 // C2ParamDescriptor -> ParamDescriptor
objcpy(ParamDescriptor * d,const C2ParamDescriptor & s)303 bool objcpy(ParamDescriptor *d, const C2ParamDescriptor &s) {
304 return ::android::objcpy(d, s);
305 }
306
307 // ParamDescriptor -> C2ParamDescriptor
objcpy(std::shared_ptr<C2ParamDescriptor> * d,const ParamDescriptor & s)308 bool objcpy(std::shared_ptr<C2ParamDescriptor> *d, const ParamDescriptor &s) {
309 return ::android::objcpy(d, s);
310 }
311
312 // C2StructDescriptor -> StructDescriptor
objcpy(StructDescriptor * d,const C2StructDescriptor & s)313 bool objcpy(StructDescriptor *d, const C2StructDescriptor &s) {
314 return ::android::objcpy(d, s);
315 }
316
317 // StructDescriptor -> C2StructDescriptor
objcpy(std::unique_ptr<C2StructDescriptor> * d,const StructDescriptor & s)318 bool objcpy(std::unique_ptr<C2StructDescriptor> *d, const StructDescriptor &s) {
319 return ::android::objcpy(d, s);
320 }
321
322 // DefaultBufferPoolSender's implementation
323
DefaultBufferPoolSender(const sp<IClientManager> & receiverManager,std::chrono::steady_clock::duration refreshInterval)324 DefaultBufferPoolSender::DefaultBufferPoolSender(
325 const sp<IClientManager>& receiverManager,
326 std::chrono::steady_clock::duration refreshInterval)
327 : mReceiverManager(receiverManager),
328 mRefreshInterval(refreshInterval) {
329 }
330
setReceiver(const sp<IClientManager> & receiverManager,std::chrono::steady_clock::duration refreshInterval)331 void DefaultBufferPoolSender::setReceiver(
332 const sp<IClientManager>& receiverManager,
333 std::chrono::steady_clock::duration refreshInterval) {
334 std::lock_guard<std::mutex> lock(mMutex);
335 if (mReceiverManager != receiverManager) {
336 mReceiverManager = receiverManager;
337 mConnections.clear();
338 }
339 mRefreshInterval = refreshInterval;
340 }
341
send(const std::shared_ptr<BufferPoolData> & bpData,BufferStatusMessage * bpMessage)342 ResultStatus DefaultBufferPoolSender::send(
343 const std::shared_ptr<BufferPoolData>& bpData,
344 BufferStatusMessage* bpMessage) {
345 int64_t connectionId = bpData->mConnectionId;
346 if (connectionId == 0) {
347 LOG(WARNING) << "registerSender -- invalid sender connection id (0).";
348 return ResultStatus::CRITICAL_ERROR;
349 }
350 std::lock_guard<std::mutex> lock(mMutex);
351 if (!mReceiverManager) {
352 LOG(ERROR) << "No access to receiver's BufferPool.";
353 return ResultStatus::NOT_FOUND;
354 }
355 if (!mSenderManager) {
356 mSenderManager = ClientManager::getInstance();
357 if (!mSenderManager) {
358 LOG(ERROR) << "Failed to retrieve local BufferPool ClientManager.";
359 return ResultStatus::CRITICAL_ERROR;
360 }
361 }
362
363 int64_t receiverConnectionId{0};
364 auto foundConnection = mConnections.find(connectionId);
365 bool isNewConnection = foundConnection == mConnections.end();
366 std::chrono::steady_clock::time_point now =
367 std::chrono::steady_clock::now();
368 if (isNewConnection ||
369 (now - foundConnection->second.lastSent > mRefreshInterval)) {
370 // Initialize the bufferpool connection.
371 ResultStatus rs =
372 mSenderManager->registerSender(mReceiverManager,
373 connectionId,
374 &receiverConnectionId);
375 if ((rs != ResultStatus::OK) && (rs != ResultStatus::ALREADY_EXISTS)) {
376 LOG(WARNING) << "registerSender -- returned error: "
377 << static_cast<int32_t>(rs)
378 << ".";
379 return rs;
380 } else if (receiverConnectionId == 0) {
381 LOG(WARNING) << "registerSender -- "
382 "invalid receiver connection id (0).";
383 return ResultStatus::CRITICAL_ERROR;
384 } else {
385 if (isNewConnection) {
386 foundConnection = mConnections.try_emplace(
387 connectionId, receiverConnectionId, now).first;
388 } else {
389 foundConnection->second.receiverConnectionId = receiverConnectionId;
390 }
391 }
392 } else {
393 receiverConnectionId = foundConnection->second.receiverConnectionId;
394 }
395
396 uint64_t transactionId;
397 int64_t timestampUs;
398 ResultStatus rs = mSenderManager->postSend(
399 receiverConnectionId, bpData, &transactionId, ×tampUs);
400 if (rs != ResultStatus::OK) {
401 LOG(ERROR) << "ClientManager::postSend -- returned error: "
402 << static_cast<int32_t>(rs)
403 << ".";
404 mConnections.erase(foundConnection);
405 return rs;
406 }
407 if (!bpMessage) {
408 LOG(ERROR) << "Null output parameter for BufferStatusMessage.";
409 mConnections.erase(foundConnection);
410 return ResultStatus::CRITICAL_ERROR;
411 }
412 bpMessage->connectionId = receiverConnectionId;
413 bpMessage->bufferId = bpData->mId;
414 bpMessage->transactionId = transactionId;
415 bpMessage->timestampUs = timestampUs;
416 foundConnection->second.lastSent = now;
417 return rs;
418 }
419
420 // std::list<std::unique_ptr<C2Work>> -> WorkBundle
objcpy(WorkBundle * d,const std::list<std::unique_ptr<C2Work>> & s,BufferPoolSender * bufferPoolSender)421 bool objcpy(
422 WorkBundle* d,
423 const std::list<std::unique_ptr<C2Work>>& s,
424 BufferPoolSender* bufferPoolSender) {
425 return ::android::objcpy(d, s, bufferPoolSender);
426 }
427
428 // WorkBundle -> std::list<std::unique_ptr<C2Work>>
objcpy(std::list<std::unique_ptr<C2Work>> * d,const WorkBundle & s)429 bool objcpy(std::list<std::unique_ptr<C2Work>>* d, const WorkBundle& s) {
430 return ::android::objcpy(d, s);
431 }
432
433 // Params -> std::vector<C2Param*>
parseParamsBlob(std::vector<C2Param * > * params,const hidl_vec<uint8_t> & blob)434 bool parseParamsBlob(std::vector<C2Param*> *params, const hidl_vec<uint8_t> &blob) {
435 return ::android::parseParamsBlob(params, blob);
436 }
437
438 // std::vector<const C2Param*> -> Params
createParamsBlob(hidl_vec<uint8_t> * blob,const std::vector<const C2Param * > & params)439 bool createParamsBlob(
440 hidl_vec<uint8_t> *blob,
441 const std::vector<const C2Param*> ¶ms) {
442 return ::android::_createParamsBlob(blob, params);
443 }
444
445 // std::vector<C2Param*> -> Params
createParamsBlob(hidl_vec<uint8_t> * blob,const std::vector<C2Param * > & params)446 bool createParamsBlob(
447 hidl_vec<uint8_t> *blob,
448 const std::vector<C2Param*> ¶ms) {
449 return ::android::_createParamsBlob(blob, params);
450 }
451
452 // std::vector<std::unique_ptr<C2Param>> -> Params
createParamsBlob(hidl_vec<uint8_t> * blob,const std::vector<std::unique_ptr<C2Param>> & params)453 bool createParamsBlob(
454 hidl_vec<uint8_t> *blob,
455 const std::vector<std::unique_ptr<C2Param>> ¶ms) {
456 return ::android::_createParamsBlob(blob, params);
457 }
458
459 // std::vector<std::unique_ptr<C2Tuning>> -> Params
createParamsBlob(hidl_vec<uint8_t> * blob,const std::vector<std::unique_ptr<C2Tuning>> & params)460 bool createParamsBlob(
461 hidl_vec<uint8_t> *blob,
462 const std::vector<std::unique_ptr<C2Tuning>> ¶ms) {
463 return ::android::_createParamsBlob(blob, params);
464 }
465
466 // std::vector<std::shared_ptr<const C2Info>> -> Params
createParamsBlob(hidl_vec<uint8_t> * blob,const std::vector<std::shared_ptr<const C2Info>> & params)467 bool createParamsBlob(
468 hidl_vec<uint8_t> *blob,
469 const std::vector<std::shared_ptr<const C2Info>> ¶ms) {
470 return ::android::_createParamsBlob(blob, params);
471 }
472
473 // Params -> std::vector<std::unique_ptr<C2Param>>
copyParamsFromBlob(std::vector<std::unique_ptr<C2Param>> * params,Params blob)474 bool copyParamsFromBlob(
475 std::vector<std::unique_ptr<C2Param>>* params,
476 Params blob) {
477 return ::android::_copyParamsFromBlob(params, blob);
478 }
479
480 // Params -> std::vector<std::unique_ptr<C2Tuning>>
copyParamsFromBlob(std::vector<std::unique_ptr<C2Tuning>> * params,Params blob)481 bool copyParamsFromBlob(
482 std::vector<std::unique_ptr<C2Tuning>>* params,
483 Params blob) {
484 return ::android::_copyParamsFromBlob(params, blob);
485 }
486
487 // Params -> update std::vector<std::unique_ptr<C2Param>>
updateParamsFromBlob(const std::vector<C2Param * > & params,const Params & blob)488 bool updateParamsFromBlob(
489 const std::vector<C2Param*>& params,
490 const Params& blob) {
491 return ::android::updateParamsFromBlob(params, blob);
492 }
493
494 // Convert BufferPool ResultStatus to c2_status_t.
toC2Status(ResultStatus rs)495 c2_status_t toC2Status(ResultStatus rs) {
496 switch (rs) {
497 case ResultStatus::OK:
498 return C2_OK;
499 case ResultStatus::NO_MEMORY:
500 return C2_NO_MEMORY;
501 case ResultStatus::ALREADY_EXISTS:
502 return C2_DUPLICATE;
503 case ResultStatus::NOT_FOUND:
504 return C2_NOT_FOUND;
505 case ResultStatus::CRITICAL_ERROR:
506 return C2_CORRUPTED;
507 default:
508 LOG(WARNING) << "Unrecognized BufferPool ResultStatus: "
509 << static_cast<int32_t>(rs) << ".";
510 return C2_CORRUPTED;
511 }
512 }
513
514 // BufferQueue-Based Block Operations
beginTransferBufferQueueBlock(const C2ConstGraphicBlock & block)515 bool beginTransferBufferQueueBlock(const C2ConstGraphicBlock& block) {
516 return ::android::BeginTransferBufferQueueBlock(block);
517 }
518
beginTransferBufferQueueBlocks(const std::list<std::unique_ptr<C2Work>> & workList,bool processInput,bool processOutput)519 void beginTransferBufferQueueBlocks(
520 const std::list<std::unique_ptr<C2Work>>& workList,
521 bool processInput,
522 bool processOutput) {
523 return ::android::BeginTransferBufferQueueBlocks(
524 workList, processInput, processOutput);
525 }
526
endTransferBufferQueueBlock(const C2ConstGraphicBlock & block,bool transfer)527 bool endTransferBufferQueueBlock(const C2ConstGraphicBlock& block,
528 bool transfer) {
529 return ::android::EndTransferBufferQueueBlock(block, transfer);
530 }
531
endTransferBufferQueueBlocks(const std::list<std::unique_ptr<C2Work>> & workList,bool transfer,bool processInput,bool processOutput)532 void endTransferBufferQueueBlocks(
533 const std::list<std::unique_ptr<C2Work>>& workList,
534 bool transfer,
535 bool processInput,
536 bool processOutput) {
537 return ::android::EndTransferBufferQueueBlocks(
538 workList, transfer, processInput, processOutput);
539 }
540
displayBufferQueueBlock(const C2ConstGraphicBlock & block)541 bool displayBufferQueueBlock(const C2ConstGraphicBlock& block) {
542 return ::android::DisplayBufferQueueBlock(block);
543 }
544
545 } // namespace utils
546 } // namespace V1_0
547 } // namespace c2
548 } // namespace media
549 } // namespace hardware
550 } // namespace android
551
552