blob: 0f056321e3096bc8260ba04d077b6db5046a79a4 [file] [log] [blame]
Yin-Chia Yehb978c382019-10-30 00:22:37 -07001/*
2 * Copyright (C) 2019 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_TAG "Camera3-OffLnSsn"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20//#define LOG_NNDEBUG 0 // Per-frame verbose logging
21
22#ifdef LOG_NNDEBUG
23#define ALOGVV(...) ALOGV(__VA_ARGS__)
24#else
25#define ALOGVV(...) ((void)0)
26#endif
27
28#include <inttypes.h>
29
30#include <utils/Trace.h>
31
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -080032#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
33
Yin-Chia Yehb978c382019-10-30 00:22:37 -070034#include "device3/Camera3OfflineSession.h"
35#include "device3/Camera3OutputStream.h"
36#include "device3/Camera3InputStream.h"
37#include "device3/Camera3SharedOutputStream.h"
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -080038#include "utils/CameraTraces.h"
Yin-Chia Yehb978c382019-10-30 00:22:37 -070039
40using namespace android::camera3;
41using namespace android::hardware::camera;
42
43namespace android {
44
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -080045Camera3OfflineSession::Camera3OfflineSession(const String8 &id,
46 const sp<camera3::Camera3Stream>& inputStream,
47 const camera3::StreamSet& offlineStreamSet,
48 camera3::BufferRecords&& bufferRecords,
49 const camera3::InFlightRequestMap& offlineReqs,
50 const Camera3OfflineStates& offlineStates,
51 sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession) :
52 mId(id),
53 mInputStream(inputStream),
54 mOutputStreams(offlineStreamSet),
55 mBufferRecords(std::move(bufferRecords)),
56 mOfflineReqs(offlineReqs),
57 mSession(offlineSession),
58 mTagMonitor(offlineStates.mTagMonitor),
59 mVendorTagId(offlineStates.mVendorTagId),
60 mUseHalBufManager(offlineStates.mUseHalBufManager),
61 mNeedFixupMonochromeTags(offlineStates.mNeedFixupMonochromeTags),
62 mUsePartialResult(offlineStates.mUsePartialResult),
63 mNumPartialResults(offlineStates.mNumPartialResults),
64 mNextResultFrameNumber(offlineStates.mNextResultFrameNumber),
65 mNextReprocessResultFrameNumber(offlineStates.mNextReprocessResultFrameNumber),
66 mNextZslStillResultFrameNumber(offlineStates.mNextZslStillResultFrameNumber),
67 mNextShutterFrameNumber(offlineStates.mNextShutterFrameNumber),
68 mNextReprocessShutterFrameNumber(offlineStates.mNextReprocessShutterFrameNumber),
69 mNextZslStillShutterFrameNumber(offlineStates.mNextZslStillShutterFrameNumber),
70 mDeviceInfo(offlineStates.mDeviceInfo),
71 mPhysicalDeviceInfoMap(offlineStates.mPhysicalDeviceInfoMap),
72 mDistortionMappers(offlineStates.mDistortionMappers),
73 mZoomRatioMappers(offlineStates.mZoomRatioMappers),
74 mStatus(STATUS_UNINITIALIZED) {
Yin-Chia Yehb978c382019-10-30 00:22:37 -070075 ATRACE_CALL();
76 ALOGV("%s: Created offline session for camera %s", __FUNCTION__, mId.string());
77}
78
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -080079Camera3OfflineSession::~Camera3OfflineSession() {
Yin-Chia Yehb978c382019-10-30 00:22:37 -070080 ATRACE_CALL();
81 ALOGV("%s: Tearing down offline session for camera id %s", __FUNCTION__, mId.string());
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -080082 disconnectImpl();
Yin-Chia Yehb978c382019-10-30 00:22:37 -070083}
84
85const String8& Camera3OfflineSession::getId() const {
86 return mId;
87}
88
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -080089status_t Camera3OfflineSession::initialize(wp<NotificationListener> listener) {
Yin-Chia Yehb978c382019-10-30 00:22:37 -070090 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -080091
92 if (mSession == nullptr) {
93 ALOGE("%s: HIDL session is null!", __FUNCTION__);
94 return DEAD_OBJECT;
95 }
96
97 {
98 std::lock_guard<std::mutex> lock(mLock);
99
100 mListener = listener;
101
102 // setup result FMQ
103 std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
104 auto resultQueueRet = mSession->getCaptureResultMetadataQueue(
105 [&resQueue](const auto& descriptor) {
106 resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
107 if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
108 ALOGE("HAL returns empty result metadata fmq, not use it");
109 resQueue = nullptr;
110 // Don't use resQueue onwards.
111 }
112 });
113 if (!resultQueueRet.isOk()) {
114 ALOGE("Transaction error when getting result metadata queue from camera session: %s",
115 resultQueueRet.description().c_str());
116 return DEAD_OBJECT;
117 }
118 mStatus = STATUS_ACTIVE;
119 }
120
121 mSession->setCallback(this);
122
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700123 return OK;
124}
125
126status_t Camera3OfflineSession::dump(int /*fd*/) {
127 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800128 std::lock_guard<std::mutex> il(mInterfaceLock);
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700129 return OK;
130}
131
132status_t Camera3OfflineSession::disconnect() {
133 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800134 return disconnectImpl();
135}
136
137status_t Camera3OfflineSession::disconnectImpl() {
138 ATRACE_CALL();
139 std::lock_guard<std::mutex> il(mInterfaceLock);
140
141 sp<NotificationListener> listener;
142 {
143 std::lock_guard<std::mutex> lock(mLock);
144 if (mStatus == STATUS_CLOSED) {
145 return OK; // don't close twice
146 } else if (mStatus == STATUS_ERROR) {
147 ALOGE("%s: offline session %s shutting down in error state",
148 __FUNCTION__, mId.string());
149 }
150 listener = mListener.promote();
151 }
152
153 ALOGV("%s: E", __FUNCTION__);
154
155 {
156 std::lock_guard<std::mutex> lock(mRequestBufferInterfaceLock);
157 mAllowRequestBuffer = false;
158 }
159
160 std::vector<wp<Camera3StreamInterface>> streams;
161 streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
162 for (size_t i = 0; i < mOutputStreams.size(); i++) {
163 streams.push_back(mOutputStreams[i]);
164 }
165 if (mInputStream != nullptr) {
166 streams.push_back(mInputStream);
167 }
168
169 mSession->close();
170
171 FlushInflightReqStates states {
172 mId, mOfflineReqsLock, mOfflineReqs, mUseHalBufManager,
173 listener, *this, mBufferRecords, *this};
174
175 camera3::flushInflightRequests(states);
176
177 {
178 std::lock_guard<std::mutex> lock(mLock);
179 mSession.clear();
180 mOutputStreams.clear();
181 mInputStream.clear();
182 mStatus = STATUS_CLOSED;
183 }
184
185 for (auto& weakStream : streams) {
186 sp<Camera3StreamInterface> stream = weakStream.promote();
187 if (stream != nullptr) {
188 ALOGE("%s: Stream %d leaked! strong reference (%d)!",
189 __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
190 }
191 }
192
193 ALOGV("%s: X", __FUNCTION__);
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700194 return OK;
195}
196
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800197status_t Camera3OfflineSession::waitForNextFrame(nsecs_t timeout) {
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700198 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800199 std::unique_lock<std::mutex> lk(mOutputLock);
200
201 while (mResultQueue.empty()) {
202 auto st = mResultSignal.wait_for(lk, std::chrono::nanoseconds(timeout));
203 if (st == std::cv_status::timeout) {
204 return TIMED_OUT;
205 }
206 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700207 return OK;
208}
209
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800210status_t Camera3OfflineSession::getNextResult(CaptureResult* frame) {
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700211 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800212 std::lock_guard<std::mutex> l(mOutputLock);
213
214 if (mResultQueue.empty()) {
215 return NOT_ENOUGH_DATA;
216 }
217
218 if (frame == nullptr) {
219 ALOGE("%s: argument cannot be NULL", __FUNCTION__);
220 return BAD_VALUE;
221 }
222
223 CaptureResult &result = *(mResultQueue.begin());
224 frame->mResultExtras = result.mResultExtras;
225 frame->mMetadata.acquire(result.mMetadata);
226 frame->mPhysicalMetadatas = std::move(result.mPhysicalMetadatas);
227 mResultQueue.erase(mResultQueue.begin());
228
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700229 return OK;
230}
231
232hardware::Return<void> Camera3OfflineSession::processCaptureResult_3_4(
233 const hardware::hidl_vec<
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800234 hardware::camera::device::V3_4::CaptureResult>& results) {
235 sp<NotificationListener> listener;
236 {
237 std::lock_guard<std::mutex> lock(mLock);
238 if (mStatus != STATUS_ACTIVE) {
239 ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
240 return hardware::Void();
241 }
242 listener = mListener.promote();
243 }
244
245 CaptureOutputStates states {
246 mId,
247 mOfflineReqsLock, mOfflineReqs,
248 mOutputLock, mResultQueue, mResultSignal,
249 mNextShutterFrameNumber,
250 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
251 mNextResultFrameNumber,
252 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
253 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
254 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
255 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mTagMonitor,
256 mInputStream, mOutputStreams, listener, *this, *this, mBufferRecords
257 };
258
259 std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
260 for (const auto& result : results) {
261 processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
262 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700263 return hardware::Void();
264}
265
266hardware::Return<void> Camera3OfflineSession::processCaptureResult(
267 const hardware::hidl_vec<
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800268 hardware::camera::device::V3_2::CaptureResult>& results) {
269 // TODO: changed impl to call into processCaptureResult_3_4 instead?
270 // might need to figure how to reduce copy though.
271 sp<NotificationListener> listener;
272 {
273 std::lock_guard<std::mutex> lock(mLock);
274 if (mStatus != STATUS_ACTIVE) {
275 ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
276 return hardware::Void();
277 }
278 listener = mListener.promote();
279 }
280
281 hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
282
283 CaptureOutputStates states {
284 mId,
285 mOfflineReqsLock, mOfflineReqs,
286 mOutputLock, mResultQueue, mResultSignal,
287 mNextShutterFrameNumber,
288 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
289 mNextResultFrameNumber,
290 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
291 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
292 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
293 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mTagMonitor,
294 mInputStream, mOutputStreams, listener, *this, *this, mBufferRecords
295 };
296
297 std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
298 for (const auto& result : results) {
299 processOneCaptureResultLocked(states, result, noPhysMetadata);
300 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700301 return hardware::Void();
302}
303
304hardware::Return<void> Camera3OfflineSession::notify(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800305 const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
306 sp<NotificationListener> listener;
307 {
308 std::lock_guard<std::mutex> lock(mLock);
309 if (mStatus != STATUS_ACTIVE) {
310 ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
311 return hardware::Void();
312 }
313 listener = mListener.promote();
314 }
315
316 CaptureOutputStates states {
317 mId,
318 mOfflineReqsLock, mOfflineReqs,
319 mOutputLock, mResultQueue, mResultSignal,
320 mNextShutterFrameNumber,
321 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
322 mNextResultFrameNumber,
323 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
324 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
325 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
326 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mTagMonitor,
327 mInputStream, mOutputStreams, listener, *this, *this, mBufferRecords
328 };
329 for (const auto& msg : msgs) {
330 camera3::notify(states, msg);
331 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700332 return hardware::Void();
333}
334
335hardware::Return<void> Camera3OfflineSession::requestStreamBuffers(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800336 const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
337 requestStreamBuffers_cb _hidl_cb) {
338 {
339 std::lock_guard<std::mutex> lock(mLock);
340 if (mStatus != STATUS_ACTIVE) {
341 ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
342 return hardware::Void();
343 }
344 }
345
346 RequestBufferStates states {
347 mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams,
348 *this, mBufferRecords, *this};
349 camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700350 return hardware::Void();
351}
352
353hardware::Return<void> Camera3OfflineSession::returnStreamBuffers(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800354 const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
355 {
356 std::lock_guard<std::mutex> lock(mLock);
357 if (mStatus != STATUS_ACTIVE) {
358 ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
359 return hardware::Void();
360 }
361 }
362
363 ReturnBufferStates states {
364 mId, mUseHalBufManager, mOutputStreams, mBufferRecords};
365 camera3::returnStreamBuffers(states, buffers);
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700366 return hardware::Void();
367}
368
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800369void Camera3OfflineSession::setErrorState(const char *fmt, ...) {
370 ATRACE_CALL();
371 std::lock_guard<std::mutex> lock(mLock);
372 va_list args;
373 va_start(args, fmt);
374
375 setErrorStateLockedV(fmt, args);
376
377 va_end(args);
378
379 //FIXME: automatically disconnect here?
380}
381
382void Camera3OfflineSession::setErrorStateLocked(const char *fmt, ...) {
383 va_list args;
384 va_start(args, fmt);
385
386 setErrorStateLockedV(fmt, args);
387
388 va_end(args);
389}
390
391void Camera3OfflineSession::setErrorStateLockedV(const char *fmt, va_list args) {
392 // Print out all error messages to log
393 String8 errorCause = String8::formatV(fmt, args);
394 ALOGE("Camera %s: %s", mId.string(), errorCause.string());
395
396 // But only do error state transition steps for the first error
397 if (mStatus == STATUS_ERROR || mStatus == STATUS_UNINITIALIZED) return;
398
399 mErrorCause = errorCause;
400
401 mStatus = STATUS_ERROR;
402
403 // Notify upstream about a device error
404 sp<NotificationListener> listener = mListener.promote();
405 if (listener != NULL) {
406 listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
407 CaptureResultExtras());
408 }
409
410 // Save stack trace. View by dumping it later.
411 CameraTraces::saveTrace();
412}
413
414void Camera3OfflineSession::onInflightEntryRemovedLocked(nsecs_t /*duration*/) {
415 if (mOfflineReqs.size() == 0) {
416 std::lock_guard<std::mutex> lock(mRequestBufferInterfaceLock);
417 mAllowRequestBuffer = false;
418 }
419}
420
421void Camera3OfflineSession::checkInflightMapLengthLocked() {
422 // Intentional empty impl.
423}
424
425void Camera3OfflineSession::onInflightMapFlushedLocked() {
426 // Intentional empty impl.
427}
428
429bool Camera3OfflineSession::startRequestBuffer() {
430 return mAllowRequestBuffer;
431}
432
433void Camera3OfflineSession::endRequestBuffer() {
434 // Intentional empty impl.
435}
436
437nsecs_t Camera3OfflineSession::getWaitDuration() {
438 const nsecs_t kBaseGetBufferWait = 3000000000; // 3 sec.
439 return kBaseGetBufferWait;
440}
441
442void Camera3OfflineSession::getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out) {
443 mBufferRecords.getInflightBufferKeys(out);
444}
445
446void Camera3OfflineSession::getInflightRequestBufferKeys(std::vector<uint64_t>* out) {
447 mBufferRecords.getInflightRequestBufferKeys(out);
448}
449
450std::vector<sp<Camera3StreamInterface>> Camera3OfflineSession::getAllStreams() {
451 std::vector<sp<Camera3StreamInterface>> ret;
452 bool hasInputStream = mInputStream != nullptr;
453 ret.reserve(mOutputStreams.size() + ((hasInputStream) ? 1 : 0));
454 if (hasInputStream) {
455 ret.push_back(mInputStream);
456 }
457 for (size_t i = 0; i < mOutputStreams.size(); i++) {
458 ret.push_back(mOutputStreams[i]);
459 }
460 return ret;
461}
462
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700463}; // namespace android