1 /*
2 * Copyright (C) 2023 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 FAILURE_DEBUG_PREFIX "CameraDeviceSession"
18
19 #include <inttypes.h>
20
21 #include <chrono>
22 #include <memory>
23
24 #include <log/log.h>
25 #include <aidlcommonsupport/NativeHandle.h>
26 #include <utils/ThreadDefs.h>
27
28 #include <aidl/android/hardware/camera/device/ErrorCode.h>
29 #include <aidl/android/hardware/graphics/common/Dataspace.h>
30
31 #include "debug.h"
32 #include "CameraDeviceSession.h"
33 #include "CameraDevice.h"
34 #include "metadata_utils.h"
35
36 #include <system/camera_metadata.h>
37
38 namespace android {
39 namespace hardware {
40 namespace camera {
41 namespace provider {
42 namespace implementation {
43
44 using aidl::android::hardware::camera::common::Status;
45 using aidl::android::hardware::camera::device::CaptureResult;
46 using aidl::android::hardware::camera::device::ErrorCode;
47 using aidl::android::hardware::camera::device::StreamRotation;
48 using aidl::android::hardware::camera::device::StreamType;
49
50 using aidl::android::hardware::graphics::common::Dataspace;
51
52 namespace {
53 constexpr char kClass[] = "CameraDeviceSession";
54
55 constexpr int64_t kOneSecondNs = 1000000000;
56 constexpr size_t kMsgQueueSize = 256 * 1024;
57
timespecAddNanos(const struct timespec t,const int64_t addNs)58 struct timespec timespecAddNanos(const struct timespec t, const int64_t addNs) {
59 const lldiv_t r = lldiv(t.tv_nsec + addNs, kOneSecondNs);
60
61 struct timespec tm;
62 tm.tv_sec = t.tv_sec + r.quot;
63 tm.tv_nsec = r.rem;
64
65 return tm;
66 }
67
timespec2nanos(const struct timespec t)68 int64_t timespec2nanos(const struct timespec t) {
69 return kOneSecondNs * t.tv_sec + t.tv_nsec;
70 }
71
pixelFormatToStr(const PixelFormat fmt,char * buf,int bufSz)72 const char* pixelFormatToStr(const PixelFormat fmt, char* buf, int bufSz) {
73 switch (fmt) {
74 case PixelFormat::UNSPECIFIED: return "UNSPECIFIED";
75 case PixelFormat::IMPLEMENTATION_DEFINED: return "IMPLEMENTATION_DEFINED";
76 case PixelFormat::YCBCR_420_888: return "YCBCR_420_888";
77 case PixelFormat::RGBA_8888: return "RGBA_8888";
78 case PixelFormat::BLOB: return "BLOB";
79 default:
80 snprintf(buf, bufSz, "0x%x", static_cast<uint32_t>(fmt));
81 return buf;
82 }
83 }
84
notifyError(ICameraDeviceCallback * cb,const int32_t frameNumber,const int32_t errorStreamId,const ErrorCode err)85 void notifyError(ICameraDeviceCallback* cb,
86 const int32_t frameNumber,
87 const int32_t errorStreamId,
88 const ErrorCode err) {
89 using aidl::android::hardware::camera::device::NotifyMsg;
90 using aidl::android::hardware::camera::device::ErrorMsg;
91 using NotifyMsgTag = NotifyMsg::Tag;
92
93 NotifyMsg msg;
94
95 {
96 ErrorMsg errorMsg;
97 errorMsg.frameNumber = frameNumber;
98 errorMsg.errorStreamId = errorStreamId;
99 errorMsg.errorCode = err;
100 msg.set<NotifyMsgTag::error>(errorMsg);
101 }
102
103 cb->notify({msg});
104 }
105
notifyShutter(ICameraDeviceCallback * cb,const int32_t frameNumber,const int64_t shutterTimestamp,const int64_t readoutTimestamp)106 void notifyShutter(ICameraDeviceCallback* cb,
107 const int32_t frameNumber,
108 const int64_t shutterTimestamp,
109 const int64_t readoutTimestamp) {
110 using aidl::android::hardware::camera::device::NotifyMsg;
111 using aidl::android::hardware::camera::device::ShutterMsg;
112 using NotifyMsgTag = NotifyMsg::Tag;
113
114 NotifyMsg msg;
115
116 {
117 ShutterMsg shutterMsg;
118 shutterMsg.frameNumber = frameNumber;
119 shutterMsg.timestamp = shutterTimestamp;
120 shutterMsg.readoutTimestamp = readoutTimestamp;
121 msg.set<NotifyMsgTag::shutter>(shutterMsg);
122 }
123
124 cb->notify({msg});
125 }
126
makeCaptureResult(const int frameNumber,CameraMetadata metadata,std::vector<StreamBuffer> outputBuffers)127 CaptureResult makeCaptureResult(const int frameNumber,
128 CameraMetadata metadata,
129 std::vector<StreamBuffer> outputBuffers) {
130 CaptureResult cr;
131 cr.frameNumber = frameNumber;
132 cr.result = std::move(metadata);
133 cr.outputBuffers = std::move(outputBuffers);
134 cr.inputBuffer.streamId = -1;
135 cr.inputBuffer.bufferId = 0;
136 cr.partialResult = cr.result.metadata.empty() ? 0 : 1;
137 return cr;
138 }
139 } // namespace
140
CameraDeviceSession(std::shared_ptr<CameraDevice> parent,std::shared_ptr<ICameraDeviceCallback> cb,hw::HwCamera & hwCamera)141 CameraDeviceSession::CameraDeviceSession(
142 std::shared_ptr<CameraDevice> parent,
143 std::shared_ptr<ICameraDeviceCallback> cb,
144 hw::HwCamera& hwCamera)
145 : mParent(std::move(parent))
146 , mCb(std::move(cb))
147 , mHwCamera(hwCamera)
148 , mRequestQueue(kMsgQueueSize, false)
149 , mResultQueue(kMsgQueueSize, false) {
150 LOG_ALWAYS_FATAL_IF(!mRequestQueue.isValid());
151 LOG_ALWAYS_FATAL_IF(!mResultQueue.isValid());
152 mCaptureThread = std::thread(&CameraDeviceSession::captureThreadLoop, this);
153 mDelayedCaptureThread = std::thread(&CameraDeviceSession::delayedCaptureThreadLoop, this);
154 }
155
~CameraDeviceSession()156 CameraDeviceSession::~CameraDeviceSession() {
157 closeImpl();
158
159 mCaptureRequests.cancel();
160 mDelayedCaptureResults.cancel();
161 mCaptureThread.join();
162 mDelayedCaptureThread.join();
163 }
164
close()165 ScopedAStatus CameraDeviceSession::close() {
166 closeImpl();
167 return ScopedAStatus::ok();
168 }
169
configureStreams(const StreamConfiguration & cfg,std::vector<HalStream> * halStreamsOut)170 ScopedAStatus CameraDeviceSession::configureStreams(
171 const StreamConfiguration& cfg,
172 std::vector<HalStream>* halStreamsOut) {
173 ALOGD("%s:%s:%d cfg={ "
174 ".streams.size=%zu, .operationMode=%u, .cfg.sessionParams.size()=%zu, "
175 " .streamConfigCounter=%d, .multiResolutionInputImage=%s }",
176 kClass, __func__, __LINE__,
177 cfg.streams.size(), static_cast<uint32_t>(cfg.operationMode),
178 cfg.sessionParams.metadata.size(), cfg.streamConfigCounter,
179 (cfg.multiResolutionInputImage ? "true" : "false"));
180
181 for (const auto& s : cfg.streams) {
182 const uint32_t dataspaceBits = static_cast<uint32_t>(s.dataSpace);
183 const uint32_t dataspaceLow = dataspaceBits & 0xFFFF;
184 const uint32_t dataspaceS =
185 (dataspaceBits & static_cast<uint32_t>(Dataspace::STANDARD_MASK)) >>
186 static_cast<uint32_t>(Dataspace::STANDARD_SHIFT);
187 const uint32_t dataspaceT =
188 (dataspaceBits & static_cast<uint32_t>(Dataspace::TRANSFER_MASK)) >>
189 static_cast<uint32_t>(Dataspace::TRANSFER_SHIFT);
190 const uint32_t dataspaceR =
191 (dataspaceBits & static_cast<uint32_t>(Dataspace::RANGE_MASK)) >>
192 static_cast<uint32_t>(Dataspace::RANGE_SHIFT);
193
194 char pixelFormatStrBuf[16];
195
196 ALOGD("%s:%s:%d stream={ .id=%d, "
197 ".streamType=%u, .width=%d, .height=%d, .format=%s, .usage=0x%" PRIx64 ", "
198 ".dataSpace={ .low=0x%x, .s=%u, .t=%u, .r=%u }, .rotation=%u, .physicalCameraId='%s', .bufferSize=%d, "
199 ".groupId=%d, .dynamicRangeProfile=0x%x }", kClass, __func__, __LINE__,
200 s.id, static_cast<unsigned>(s.streamType), s.width, s.height,
201 pixelFormatToStr(s.format, pixelFormatStrBuf, sizeof(pixelFormatStrBuf)),
202 static_cast<uint64_t>(s.usage),
203 dataspaceLow, dataspaceS, dataspaceT, dataspaceR,
204 static_cast<unsigned>(s.rotation),
205 s.physicalCameraId.c_str(), s.bufferSize, s.groupId,
206 static_cast<unsigned>(s.dynamicRangeProfile)
207 );
208 }
209
210 auto [status, halStreams] = configureStreamsStatic(cfg, mHwCamera);
211 if (status != Status::OK) {
212 return toScopedAStatus(status);
213 }
214
215 const size_t nStreams = cfg.streams.size();
216 LOG_ALWAYS_FATAL_IF(halStreams.size() != nStreams);
217
218 if (mHwCamera.configure(cfg.sessionParams, nStreams,
219 cfg.streams.data(), halStreams.data())) {
220 mStreamBufferCache.clearStreamInfo();
221 *halStreamsOut = std::move(halStreams);
222 return ScopedAStatus::ok();
223 } else {
224 return toScopedAStatus(FAILURE(Status::INTERNAL_ERROR));
225 }
226 }
227
constructDefaultRequestSettings(const RequestTemplate tpl,CameraMetadata * metadata)228 ScopedAStatus CameraDeviceSession::constructDefaultRequestSettings(
229 const RequestTemplate tpl,
230 CameraMetadata* metadata) {
231 auto maybeMetadata = serializeCameraMetadataMap(
232 mParent->constructDefaultRequestSettings(tpl));
233
234 if (maybeMetadata) {
235 *metadata = std::move(maybeMetadata.value());
236 return ScopedAStatus::ok();
237 } else {
238 return toScopedAStatus(Status::INTERNAL_ERROR);
239 }
240 }
241
flush()242 ScopedAStatus CameraDeviceSession::flush() {
243 flushImpl(std::chrono::steady_clock::now());
244 return ScopedAStatus::ok();
245 }
246
getCaptureRequestMetadataQueue(MQDescriptor<int8_t,SynchronizedReadWrite> * desc)247 ScopedAStatus CameraDeviceSession::getCaptureRequestMetadataQueue(
248 MQDescriptor<int8_t, SynchronizedReadWrite>* desc) {
249 *desc = mRequestQueue.dupeDesc();
250 return ScopedAStatus::ok();
251 }
252
getCaptureResultMetadataQueue(MQDescriptor<int8_t,SynchronizedReadWrite> * desc)253 ScopedAStatus CameraDeviceSession::getCaptureResultMetadataQueue(
254 MQDescriptor<int8_t, SynchronizedReadWrite>* desc) {
255 *desc = mResultQueue.dupeDesc();
256 return ScopedAStatus::ok();
257 }
258
isReconfigurationRequired(const CameraMetadata &,const CameraMetadata &,bool * resultOut)259 ScopedAStatus CameraDeviceSession::isReconfigurationRequired(
260 const CameraMetadata& /*oldParams*/,
261 const CameraMetadata& /*newParams*/,
262 bool* resultOut) {
263 *resultOut = false;
264 return ScopedAStatus::ok();
265 }
266
processCaptureRequest(const std::vector<CaptureRequest> & requests,const std::vector<BufferCache> & cachesToRemove,int32_t * countOut)267 ScopedAStatus CameraDeviceSession::processCaptureRequest(
268 const std::vector<CaptureRequest>& requests,
269 const std::vector<BufferCache>& cachesToRemove,
270 int32_t* countOut) {
271 for (const BufferCache& bc : cachesToRemove) {
272 mStreamBufferCache.remove(bc.bufferId);
273 }
274
275 int count = 0;
276 for (const CaptureRequest& r : requests) {
277 const Status s = processOneCaptureRequest(r);
278 if (s == Status::OK) {
279 ++count;
280 } else {
281 *countOut = count;
282 return toScopedAStatus(s);
283 }
284 }
285
286 *countOut = count;
287 return ScopedAStatus::ok();
288 }
289
signalStreamFlush(const std::vector<int32_t> &,const int32_t)290 ScopedAStatus CameraDeviceSession::signalStreamFlush(
291 const std::vector<int32_t>& /*streamIds*/,
292 const int32_t /*streamConfigCounter*/) {
293 return toScopedAStatus(FAILURE(Status::OPERATION_NOT_SUPPORTED));
294 }
295
switchToOffline(const std::vector<int32_t> &,CameraOfflineSessionInfo *,std::shared_ptr<ICameraOfflineSession> *)296 ScopedAStatus CameraDeviceSession::switchToOffline(
297 const std::vector<int32_t>& /*streamsToKeep*/,
298 CameraOfflineSessionInfo* /*offlineSessionInfo*/,
299 std::shared_ptr<ICameraOfflineSession>* /*session*/) {
300 return toScopedAStatus(FAILURE(Status::OPERATION_NOT_SUPPORTED));
301 }
302
repeatingRequestEnd(const int32_t,const std::vector<int32_t> &)303 ScopedAStatus CameraDeviceSession::repeatingRequestEnd(
304 const int32_t /*frameNumber*/,
305 const std::vector<int32_t>& /*streamIds*/) {
306 return ScopedAStatus::ok();
307 }
308
isStreamCombinationSupported(const StreamConfiguration & cfg,hw::HwCamera & hwCamera)309 bool CameraDeviceSession::isStreamCombinationSupported(const StreamConfiguration& cfg,
310 hw::HwCamera& hwCamera) {
311 const auto [status, unused] = configureStreamsStatic(cfg, hwCamera);
312 return status == Status::OK;
313 }
314
closeImpl()315 void CameraDeviceSession::closeImpl() {
316 flushImpl(std::chrono::steady_clock::now());
317 mHwCamera.close();
318 }
319
flushImpl(const std::chrono::steady_clock::time_point start)320 void CameraDeviceSession::flushImpl(const std::chrono::steady_clock::time_point start) {
321 mFlushing = true;
322 waitFlushingDone(start);
323 mFlushing = false;
324 }
325
waitFlushingDone(const std::chrono::steady_clock::time_point start)326 int CameraDeviceSession::waitFlushingDone(const std::chrono::steady_clock::time_point start) {
327 std::unique_lock<std::mutex> lock(mNumBuffersInFlightMtx);
328 if (mNumBuffersInFlight == 0) {
329 return 0;
330 }
331
332 using namespace std::chrono_literals;
333 constexpr int kRecommendedDeadlineMs = 100;
334 constexpr int kFatalDeadlineMs = 1000;
335 const auto fatalDeadline = start + (1ms * kFatalDeadlineMs);
336
337 const auto checkIfNoBuffersInFlight = [this](){ return mNumBuffersInFlight == 0; };
338
339 if (mNoBuffersInFlight.wait_until(lock, fatalDeadline, checkIfNoBuffersInFlight)) {
340 const int waitedForMs = (std::chrono::steady_clock::now() - start) / 1ms;
341
342 if (waitedForMs > kRecommendedDeadlineMs) {
343 ALOGW("%s:%s:%d: flushing took %dms, Android "
344 "recommends %dms latency and requires no more than %dms",
345 kClass, __func__, __LINE__, waitedForMs, kRecommendedDeadlineMs,
346 kFatalDeadlineMs);
347 }
348
349 return waitedForMs;
350 } else {
351 LOG_ALWAYS_FATAL("%s:%s:%d: %zu buffers are still in "
352 "flight after %dms of waiting, some buffers might have "
353 "leaked", kClass, __func__, __LINE__, mNumBuffersInFlight,
354 kFatalDeadlineMs);
355 }
356 }
357
358 std::pair<Status, std::vector<HalStream>>
configureStreamsStatic(const StreamConfiguration & cfg,hw::HwCamera & hwCamera)359 CameraDeviceSession::configureStreamsStatic(const StreamConfiguration& cfg,
360 hw::HwCamera& hwCamera) {
361 if (cfg.multiResolutionInputImage) {
362 return {FAILURE(Status::OPERATION_NOT_SUPPORTED), {}};
363 }
364
365 const size_t streamsSize = cfg.streams.size();
366 if (!streamsSize) {
367 return {FAILURE(Status::ILLEGAL_ARGUMENT), {}};
368 }
369
370 std::vector<HalStream> halStreams;
371 halStreams.reserve(streamsSize);
372
373 for (const auto& s : cfg.streams) {
374 if (s.streamType == StreamType::INPUT) {
375 return {FAILURE(Status::OPERATION_NOT_SUPPORTED), {}};
376 }
377
378 if (s.width <= 0) {
379 return {FAILURE(Status::ILLEGAL_ARGUMENT), {}};
380 }
381
382 if (s.height <= 0) {
383 return {FAILURE(Status::ILLEGAL_ARGUMENT), {}};
384 }
385
386 if (s.rotation != StreamRotation::ROTATION_0) {
387 return {FAILURE(Status::ILLEGAL_ARGUMENT), {}};
388 }
389
390 if (s.bufferSize < 0) {
391 return {FAILURE(Status::ILLEGAL_ARGUMENT), {}};
392 }
393
394 HalStream hs;
395 std::tie(hs.overrideFormat, hs.producerUsage,
396 hs.overrideDataSpace, hs.maxBuffers) =
397 hwCamera.overrideStreamParams(s.format, s.usage, s.dataSpace);
398
399 if (hs.maxBuffers <= 0) {
400 switch (hs.maxBuffers) {
401 case hw::HwCamera::kErrorBadFormat:
402 ALOGE("%s:%s:%d unexpected format=0x%" PRIx32,
403 kClass, __func__, __LINE__, static_cast<uint32_t>(s.format));
404 return {Status::ILLEGAL_ARGUMENT, {}};
405
406 case hw::HwCamera::kErrorBadUsage:
407 ALOGE("%s:%s:%d unexpected usage=0x%" PRIx64
408 " for format=0x%" PRIx32 " and dataSpace=0x%" PRIx32,
409 kClass, __func__, __LINE__, static_cast<uint64_t>(s.usage),
410 static_cast<uint32_t>(s.format),
411 static_cast<uint32_t>(s.dataSpace));
412 return {Status::ILLEGAL_ARGUMENT, {}};
413
414 case hw::HwCamera::kErrorBadDataspace:
415 ALOGE("%s:%s:%d unexpected dataSpace=0x%" PRIx32
416 " for format=0x%" PRIx32 " and usage=0x%" PRIx64,
417 kClass, __func__, __LINE__, static_cast<uint32_t>(s.dataSpace),
418 static_cast<uint32_t>(s.format),
419 static_cast<uint64_t>(s.usage));
420 return {Status::ILLEGAL_ARGUMENT, {}};
421
422 default:
423 ALOGE("%s:%s:%d something is not right for format=0x%" PRIx32
424 " usage=0x%" PRIx64 " and dataSpace=0x%" PRIx32,
425 kClass, __func__, __LINE__, static_cast<uint32_t>(s.format),
426 static_cast<uint64_t>(s.usage),
427 static_cast<uint32_t>(s.dataSpace));
428 return {Status::ILLEGAL_ARGUMENT, {}};
429 }
430 }
431
432 hs.id = s.id;
433 hs.consumerUsage = static_cast<BufferUsage>(0);
434 hs.physicalCameraId = s.physicalCameraId;
435 hs.supportOffline = false;
436
437 halStreams.push_back(std::move(hs));
438 }
439
440 return {Status::OK, std::move(halStreams)};
441 }
442
processOneCaptureRequest(const CaptureRequest & request)443 Status CameraDeviceSession::processOneCaptureRequest(const CaptureRequest& request) {
444 // If inputBuffer is valid, the request is for reprocessing
445 if (!isAidlNativeHandleEmpty(request.inputBuffer.buffer)) {
446 return FAILURE(Status::OPERATION_NOT_SUPPORTED);
447 }
448
449 if (request.inputWidth || request.inputHeight) {
450 return FAILURE(Status::OPERATION_NOT_SUPPORTED);
451 }
452
453 if (!request.physicalCameraSettings.empty()) {
454 return FAILURE(Status::OPERATION_NOT_SUPPORTED);
455 }
456
457 const size_t outputBuffersSize = request.outputBuffers.size();
458
459 if (outputBuffersSize == 0) {
460 return FAILURE(Status::ILLEGAL_ARGUMENT);
461 }
462
463 HwCaptureRequest hwReq;
464
465 if (request.fmqSettingsSize < 0) {
466 return FAILURE(Status::ILLEGAL_ARGUMENT);
467 } else if (request.fmqSettingsSize > 0) {
468 CameraMetadata tmp;
469 tmp.metadata.resize(request.fmqSettingsSize);
470
471 if (mRequestQueue.read(
472 reinterpret_cast<int8_t*>(tmp.metadata.data()),
473 request.fmqSettingsSize)) {
474 hwReq.metadataUpdate = std::move(tmp);
475 } else {
476 return FAILURE(Status::INTERNAL_ERROR);
477 }
478 } else if (!request.settings.metadata.empty()) {
479 hwReq.metadataUpdate = request.settings;
480 }
481
482 hwReq.buffers.resize(outputBuffersSize);
483 for (size_t i = 0; i < outputBuffersSize; ++i) {
484 hwReq.buffers[i] = mStreamBufferCache.update(request.outputBuffers[i]);
485 }
486
487 {
488 std::lock_guard<std::mutex> guard(mNumBuffersInFlightMtx);
489 mNumBuffersInFlight += outputBuffersSize;
490 }
491
492 hwReq.frameNumber = request.frameNumber;
493
494 if (mCaptureRequests.put(&hwReq)) {
495 return Status::OK;
496 } else {
497 disposeCaptureRequest(std::move(hwReq));
498 return FAILURE(Status::INTERNAL_ERROR);
499 }
500 }
501
captureThreadLoop()502 void CameraDeviceSession::captureThreadLoop() {
503 setThreadPriority(SP_FOREGROUND, ANDROID_PRIORITY_VIDEO);
504
505 struct timespec nextFrameT;
506 clock_gettime(CLOCK_MONOTONIC, &nextFrameT);
507 while (true) {
508 std::optional<HwCaptureRequest> maybeReq = mCaptureRequests.get();
509 if (maybeReq.has_value()) {
510 HwCaptureRequest& req = maybeReq.value();
511 if (mFlushing) {
512 disposeCaptureRequest(std::move(req));
513 } else {
514 nextFrameT = captureOneFrame(nextFrameT, std::move(req));
515 }
516 } else {
517 break;
518 }
519 }
520 }
521
captureOneFrame(struct timespec nextFrameT,HwCaptureRequest req)522 struct timespec CameraDeviceSession::captureOneFrame(struct timespec nextFrameT,
523 HwCaptureRequest req) {
524 struct timespec now;
525 clock_gettime(CLOCK_MONOTONIC, &now);
526 if (std::make_pair(now.tv_sec, now.tv_nsec) <
527 std::make_pair(nextFrameT.tv_sec, nextFrameT.tv_nsec)) {
528 clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &nextFrameT, nullptr);
529 } else {
530 nextFrameT = now;
531 }
532
533 const int32_t frameNumber = req.frameNumber;
534
535 auto [frameDurationNs, exposureDurationNs, metadata,
536 outputBuffers, delayedOutputBuffers] =
537 mHwCamera.processCaptureRequest(std::move(req.metadataUpdate),
538 {req.buffers.begin(), req.buffers.end()});
539
540 for (hw::DelayedStreamBuffer& dsb : delayedOutputBuffers) {
541 DelayedCaptureResult dcr;
542 dcr.delayedBuffer = std::move(dsb);
543 dcr.frameNumber = frameNumber;
544 if (!mDelayedCaptureResults.put(&dcr)) {
545 // `delayedBuffer(false)` only releases the buffer (fast).
546 outputBuffers.push_back(dcr.delayedBuffer(false));
547 }
548 }
549
550 const int64_t shutterTimestampNs = timespec2nanos(nextFrameT);
551 notifyShutter(&*mCb, frameNumber, shutterTimestampNs, shutterTimestampNs + exposureDurationNs);
552 metadataSetShutterTimestamp(&metadata, shutterTimestampNs);
553 consumeCaptureResult(makeCaptureResult(frameNumber,
554 std::move(metadata), std::move(outputBuffers)));
555
556 if (frameDurationNs > 0) {
557 nextFrameT = timespecAddNanos(nextFrameT, frameDurationNs);
558 } else {
559 notifyError(&*mCb, frameNumber, -1, ErrorCode::ERROR_DEVICE);
560 }
561
562 return nextFrameT;
563 }
564
delayedCaptureThreadLoop()565 void CameraDeviceSession::delayedCaptureThreadLoop() {
566 while (true) {
567 std::optional<DelayedCaptureResult> maybeDCR = mDelayedCaptureResults.get();
568 if (maybeDCR.has_value()) {
569 const DelayedCaptureResult& dcr = maybeDCR.value();
570
571 // `dcr.delayedBuffer(true)` is expected to be slow, so we do not
572 // produce too much IPC traffic here. This also returns buffes to
573 // the framework earlier to reuse in capture requests.
574 std::vector<StreamBuffer> outputBuffers(1);
575 outputBuffers.front() = dcr.delayedBuffer(!mFlushing);
576 consumeCaptureResult(makeCaptureResult(dcr.frameNumber,
577 {}, std::move(outputBuffers)));
578 } else {
579 break;
580 }
581 }
582 }
583
disposeCaptureRequest(HwCaptureRequest req)584 void CameraDeviceSession::disposeCaptureRequest(HwCaptureRequest req) {
585 notifyError(&*mCb, req.frameNumber, -1, ErrorCode::ERROR_REQUEST);
586
587 const size_t reqBuffersSize = req.buffers.size();
588
589 {
590 std::vector<StreamBuffer> outputBuffers(reqBuffersSize);
591
592 for (size_t i = 0; i < reqBuffersSize; ++i) {
593 CachedStreamBuffer* csb = req.buffers[i];
594 LOG_ALWAYS_FATAL_IF(!csb); // otherwise mNumBuffersInFlight will be hard
595 outputBuffers[i] = csb->finish(false);
596 }
597
598 std::vector<CaptureResult> crs(1);
599 crs.front() = makeCaptureResult(req.frameNumber, {},
600 std::move(outputBuffers));
601
602 std::lock_guard<std::mutex> guard(mResultQueueMutex);
603 mCb->processCaptureResult(std::move(crs));
604 }
605
606 notifyBuffersReturned(reqBuffersSize);
607 }
608
consumeCaptureResult(CaptureResult cr)609 void CameraDeviceSession::consumeCaptureResult(CaptureResult cr) {
610 const size_t numBuffers = cr.outputBuffers.size();
611
612 {
613 std::lock_guard<std::mutex> guard(mResultQueueMutex);
614 const size_t metadataSize = cr.result.metadata.size();
615 if ((metadataSize > 0) && mResultQueue.write(
616 reinterpret_cast<int8_t*>(cr.result.metadata.data()),
617 metadataSize)) {
618 cr.fmqResultSize = metadataSize;
619 cr.result.metadata.clear();
620 }
621
622 std::vector<CaptureResult> crs(1);
623 crs.front() = std::move(cr);
624 mCb->processCaptureResult(std::move(crs));
625 }
626
627 notifyBuffersReturned(numBuffers);
628 }
629
notifyBuffersReturned(const size_t numBuffersToReturn)630 void CameraDeviceSession::notifyBuffersReturned(const size_t numBuffersToReturn) {
631 std::lock_guard<std::mutex> guard(mNumBuffersInFlightMtx);
632 LOG_ALWAYS_FATAL_IF(mNumBuffersInFlight < numBuffersToReturn,
633 "mNumBuffersInFlight=%zu numBuffersToReturn=%zu",
634 mNumBuffersInFlight, numBuffersToReturn);
635
636 mNumBuffersInFlight -= numBuffersToReturn;
637
638 if (mNumBuffersInFlight == 0) {
639 mNoBuffersInFlight.notify_all();
640 }
641 }
642
643 } // namespace implementation
644 } // namespace provider
645 } // namespace camera
646 } // namespace hardware
647 } // namespace android
648