blob: e94bc62be4152831400655db3c8fb5da9b585634 [file] [log] [blame]
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001/*
2 * Copyright (C) 2016 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 "CamDevSession@3.2-impl"
18#include <android/log.h>
19
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080020#include <set>
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070021#include <utils/Trace.h>
22#include <hardware/gralloc.h>
23#include <hardware/gralloc1.h>
24#include "CameraDeviceSession.h"
25
26namespace android {
27namespace hardware {
28namespace camera {
29namespace device {
30namespace V3_2 {
31namespace implementation {
32
Yifan Hong1192e1d2017-04-11 14:45:00 -070033// Size of request metadata fast message queue. Change to 0 to always use hwbinder buffer.
34static constexpr size_t CAMERA_REQUEST_METADATA_QUEUE_SIZE = 1 << 20 /* 1MB */;
Yifan Hong993e3d02017-04-12 16:31:23 -070035// Size of result metadata fast message queue. Change to 0 to always use hwbinder buffer.
36static constexpr size_t CAMERA_RESULT_METADATA_QUEUE_SIZE = 1 << 20 /* 1MB */;
Yifan Hong1192e1d2017-04-11 14:45:00 -070037
Yin-Chia Yeh248ed702017-01-23 17:27:26 -080038HandleImporter& CameraDeviceSession::sHandleImporter = HandleImporter::getInstance();
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080039const int CameraDeviceSession::ResultBatcher::NOT_BATCHED;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070040
41CameraDeviceSession::CameraDeviceSession(
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080042 camera3_device_t* device,
43 const camera_metadata_t* deviceInfo,
44 const sp<ICameraDeviceCallback>& callback) :
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070045 camera3_callback_ops({&sProcessCaptureResult, &sNotify}),
46 mDevice(device),
Emilian Peev7d52a6f2017-04-07 09:53:48 +010047 mDeviceVersion(device->common.version),
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080048 mResultBatcher(callback) {
49
50 mDeviceInfo = deviceInfo;
51 uint32_t numPartialResults = 1;
52 camera_metadata_entry partialResultsCount =
53 mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
54 if (partialResultsCount.count > 0) {
55 numPartialResults = partialResultsCount.data.i32[0];
56 }
57 mResultBatcher.setNumPartialResults(numPartialResults);
58
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070059 mInitFail = initialize();
60}
61
62bool CameraDeviceSession::initialize() {
63 /** Initialize device with callback functions */
64 ATRACE_BEGIN("camera3->initialize");
65 status_t res = mDevice->ops->initialize(mDevice, this);
66 ATRACE_END();
67
68 if (res != OK) {
69 ALOGE("%s: Unable to initialize HAL device: %s (%d)",
70 __FUNCTION__, strerror(-res), res);
71 mDevice->common.close(&mDevice->common);
72 mClosed = true;
73 return true;
74 }
Yifan Hong1192e1d2017-04-11 14:45:00 -070075
76 mRequestMetadataQueue = std::make_unique<RequestMetadataQueue>(
77 CAMERA_REQUEST_METADATA_QUEUE_SIZE, false /* non blocking */);
78 if (!mRequestMetadataQueue->isValid()) {
Yifan Hong993e3d02017-04-12 16:31:23 -070079 ALOGE("%s: invalid request fmq", __FUNCTION__);
Yifan Hong1192e1d2017-04-11 14:45:00 -070080 return true;
81 }
Yifan Hong993e3d02017-04-12 16:31:23 -070082 mResultMetadataQueue = std::make_shared<RequestMetadataQueue>(
83 CAMERA_RESULT_METADATA_QUEUE_SIZE, false /* non blocking */);
84 if (!mResultMetadataQueue->isValid()) {
85 ALOGE("%s: invalid result fmq", __FUNCTION__);
86 return true;
87 }
88 mResultBatcher.setResultMetadataQueue(mResultMetadataQueue);
Yifan Hong1192e1d2017-04-11 14:45:00 -070089
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070090 return false;
91}
92
93CameraDeviceSession::~CameraDeviceSession() {
94 if (!isClosed()) {
95 ALOGE("CameraDeviceSession deleted before close!");
96 close();
97 }
98}
99
100bool CameraDeviceSession::isClosed() {
101 Mutex::Autolock _l(mStateLock);
102 return mClosed;
103}
104
105Status CameraDeviceSession::initStatus() const {
106 Mutex::Autolock _l(mStateLock);
107 Status status = Status::OK;
108 if (mInitFail) {
109 status = Status::INTERNAL_ERROR;
110 } else if (mDisconnected) {
111 status = Status::CAMERA_DISCONNECTED;
112 } else if (mClosed) {
113 status = Status::INTERNAL_ERROR;
114 }
115 return status;
116}
117
118void CameraDeviceSession::disconnect() {
119 Mutex::Autolock _l(mStateLock);
120 mDisconnected = true;
121 ALOGW("%s: Camera device is disconnected. Closing.", __FUNCTION__);
122 if (!mClosed) {
123 mDevice->common.close(&mDevice->common);
124 mClosed = true;
125 }
126}
127
128void CameraDeviceSession::dumpState(const native_handle_t* fd) {
129 if (!isClosed()) {
130 mDevice->ops->dump(mDevice, fd->data[0]);
131 }
132}
133
134Status CameraDeviceSession::importRequest(
135 const CaptureRequest& request,
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800136 hidl_vec<buffer_handle_t*>& allBufPtrs,
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700137 hidl_vec<int>& allFences) {
138 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800139 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700140 size_t numOutputBufs = request.outputBuffers.size();
141 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
142 // Validate all I/O buffers
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800143 hidl_vec<buffer_handle_t> allBufs;
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800144 hidl_vec<uint64_t> allBufIds;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700145 allBufs.resize(numBufs);
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800146 allBufIds.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800147 allBufPtrs.resize(numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700148 allFences.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800149 std::vector<int32_t> streamIds(numBufs);
150
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700151 for (size_t i = 0; i < numOutputBufs; i++) {
152 allBufs[i] = request.outputBuffers[i].buffer.getNativeHandle();
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800153 allBufIds[i] = request.outputBuffers[i].bufferId;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800154 allBufPtrs[i] = &allBufs[i];
155 streamIds[i] = request.outputBuffers[i].streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700156 }
157 if (hasInputBuf) {
158 allBufs[numOutputBufs] = request.inputBuffer.buffer.getNativeHandle();
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800159 allBufIds[numOutputBufs] = request.inputBuffer.bufferId;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800160 allBufPtrs[numOutputBufs] = &allBufs[numOutputBufs];
161 streamIds[numOutputBufs] = request.inputBuffer.streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700162 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800163
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700164 for (size_t i = 0; i < numBufs; i++) {
165 buffer_handle_t buf = allBufs[i];
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800166 uint64_t bufId = allBufIds[i];
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800167 CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]];
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800168 if (cbs.count(bufId) == 0) {
169 if (buf == nullptr) {
170 ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
171 return Status::ILLEGAL_ARGUMENT;
172 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800173 // Register a newly seen buffer
174 buffer_handle_t importedBuf = buf;
175 sHandleImporter.importBuffer(importedBuf);
176 if (importedBuf == nullptr) {
177 ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i);
178 return Status::INTERNAL_ERROR;
179 } else {
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800180 cbs[bufId] = importedBuf;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800181 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700182 }
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800183 allBufPtrs[i] = &cbs[bufId];
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700184 }
185
186 // All buffers are imported. Now validate output buffer acquire fences
187 for (size_t i = 0; i < numOutputBufs; i++) {
188 if (!sHandleImporter.importFence(
189 request.outputBuffers[i].acquireFence, allFences[i])) {
190 ALOGE("%s: output buffer %zu acquire fence is invalid", __FUNCTION__, i);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800191 cleanupInflightFences(allFences, i);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700192 return Status::INTERNAL_ERROR;
193 }
194 }
195
196 // Validate input buffer acquire fences
197 if (hasInputBuf) {
198 if (!sHandleImporter.importFence(
199 request.inputBuffer.acquireFence, allFences[numOutputBufs])) {
200 ALOGE("%s: input buffer acquire fence is invalid", __FUNCTION__);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800201 cleanupInflightFences(allFences, numOutputBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700202 return Status::INTERNAL_ERROR;
203 }
204 }
205 return Status::OK;
206}
207
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800208void CameraDeviceSession::cleanupInflightFences(
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700209 hidl_vec<int>& allFences, size_t numFences) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700210 for (size_t j = 0; j < numFences; j++) {
211 sHandleImporter.closeFence(allFences[j]);
212 }
213}
214
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800215CameraDeviceSession::ResultBatcher::ResultBatcher(
216 const sp<ICameraDeviceCallback>& callback) : mCallback(callback) {};
217
218bool CameraDeviceSession::ResultBatcher::InflightBatch::allDelivered() const {
219 if (!mShutterDelivered) return false;
220
221 if (mPartialResultProgress < mNumPartialResults) {
222 return false;
223 }
224
225 for (const auto& pair : mBatchBufs) {
226 if (!pair.second.mDelivered) {
227 return false;
228 }
229 }
230 return true;
231}
232
233void CameraDeviceSession::ResultBatcher::setNumPartialResults(uint32_t n) {
234 Mutex::Autolock _l(mLock);
235 mNumPartialResults = n;
236}
237
238void CameraDeviceSession::ResultBatcher::setBatchedStreams(
239 const std::vector<int>& streamsToBatch) {
240 Mutex::Autolock _l(mLock);
241 mStreamsToBatch = streamsToBatch;
242}
243
Yifan Hong993e3d02017-04-12 16:31:23 -0700244void CameraDeviceSession::ResultBatcher::setResultMetadataQueue(std::shared_ptr<ResultMetadataQueue> q) {
245 Mutex::Autolock _l(mLock);
246 mResultMetadataQueue = q;
247}
248
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800249void CameraDeviceSession::ResultBatcher::registerBatch(
250 const hidl_vec<CaptureRequest>& requests) {
251 auto batch = std::make_shared<InflightBatch>();
252 batch->mFirstFrame = requests[0].frameNumber;
253 batch->mBatchSize = requests.size();
254 batch->mLastFrame = batch->mFirstFrame + batch->mBatchSize - 1;
255 batch->mNumPartialResults = mNumPartialResults;
256 for (int id : mStreamsToBatch) {
257 batch->mBatchBufs[id] = InflightBatch::BufferBatch();
258 }
259 Mutex::Autolock _l(mLock);
260 mInflightBatches.push_back(batch);
261}
262
263std::pair<int, std::shared_ptr<CameraDeviceSession::ResultBatcher::InflightBatch>>
264CameraDeviceSession::ResultBatcher::getBatch(
265 uint32_t frameNumber) {
266 Mutex::Autolock _l(mLock);
267 int numBatches = mInflightBatches.size();
268 if (numBatches == 0) {
269 return std::make_pair(NOT_BATCHED, nullptr);
270 }
271 uint32_t frameMin = mInflightBatches[0]->mFirstFrame;
272 uint32_t frameMax = mInflightBatches[numBatches - 1]->mLastFrame;
273 if (frameNumber < frameMin || frameNumber > frameMax) {
274 return std::make_pair(NOT_BATCHED, nullptr);
275 }
276 for (int i = 0; i < numBatches; i++) {
277 if (frameNumber >= mInflightBatches[i]->mFirstFrame &&
278 frameNumber <= mInflightBatches[i]->mLastFrame) {
279 return std::make_pair(i, mInflightBatches[i]);
280 }
281 }
282 return std::make_pair(NOT_BATCHED, nullptr);
283}
284
285void CameraDeviceSession::ResultBatcher::checkAndRemoveFirstBatch() {
286 Mutex::Autolock _l(mLock);
287 if (mInflightBatches.size() > 0) {
288 std::shared_ptr<InflightBatch> batch = mInflightBatches[0];
289 bool shouldRemove = false;
290 {
291 Mutex::Autolock _l(batch->mLock);
292 if (batch->allDelivered()) {
293 batch->mRemoved = true;
294 shouldRemove = true;
295 }
296 }
297 if (shouldRemove) {
298 mInflightBatches.pop_front();
299 }
300 }
301}
302
303void CameraDeviceSession::ResultBatcher::sendBatchShutterCbsLocked(std::shared_ptr<InflightBatch> batch) {
304 if (batch->mShutterDelivered) {
305 ALOGW("%s: batch shutter callback already sent!", __FUNCTION__);
306 return;
307 }
308
309 mCallback->notify(batch->mShutterMsgs);
310 batch->mShutterDelivered = true;
311 batch->mShutterMsgs.clear();
312}
313
314void CameraDeviceSession::ResultBatcher::freeReleaseFences(hidl_vec<CaptureResult>& results) {
315 for (auto& result : results) {
316 if (result.inputBuffer.releaseFence.getNativeHandle() != nullptr) {
317 native_handle_t* handle = const_cast<native_handle_t*>(
318 result.inputBuffer.releaseFence.getNativeHandle());
319 native_handle_delete(handle);
320 }
321 for (auto& buf : result.outputBuffers) {
322 if (buf.releaseFence.getNativeHandle() != nullptr) {
323 native_handle_t* handle = const_cast<native_handle_t*>(
324 buf.releaseFence.getNativeHandle());
325 native_handle_delete(handle);
326 }
327 }
328 }
329 return;
330}
331
332void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(std::shared_ptr<InflightBatch> batch) {
333 sendBatchBuffersLocked(batch, mStreamsToBatch);
334}
335
336void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(
337 std::shared_ptr<InflightBatch> batch, const std::vector<int>& streams) {
338 size_t batchSize = 0;
339 for (int streamId : streams) {
340 auto it = batch->mBatchBufs.find(streamId);
341 if (it != batch->mBatchBufs.end()) {
342 InflightBatch::BufferBatch& bb = it->second;
343 if (bb.mDelivered) {
344 continue;
345 }
346 if (bb.mBuffers.size() > batchSize) {
347 batchSize = bb.mBuffers.size();
348 }
349 } else {
350 ALOGE("%s: stream ID %d is not batched!", __FUNCTION__, streamId);
351 return;
352 }
353 }
354
355 if (batchSize == 0) {
356 ALOGW("%s: there is no buffer to be delivered for this batch.", __FUNCTION__);
357 for (int streamId : streams) {
358 InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
359 bb.mDelivered = true;
360 }
361 return;
362 }
363
364 hidl_vec<CaptureResult> results;
365 results.resize(batchSize);
366 for (size_t i = 0; i < batchSize; i++) {
367 results[i].frameNumber = batch->mFirstFrame + i;
Yifan Hong993e3d02017-04-12 16:31:23 -0700368 results[i].fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800369 results[i].partialResult = 0; // 0 for buffer only results
370 results[i].inputBuffer.streamId = -1;
371 results[i].inputBuffer.bufferId = 0;
372 results[i].inputBuffer.buffer = nullptr;
373 std::vector<StreamBuffer> outBufs;
374 for (int streamId : streams) {
375 InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
376 if (bb.mDelivered) {
377 continue;
378 }
379 if (i < bb.mBuffers.size()) {
380 outBufs.push_back(bb.mBuffers[i]);
381 }
382 }
383 results[i].outputBuffers = outBufs;
384 }
Yifan Hong993e3d02017-04-12 16:31:23 -0700385 invokeProcessCaptureResultCallback(results, /* tryWriteFmq */false);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800386 freeReleaseFences(results);
387 for (int streamId : streams) {
388 InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
389 bb.mDelivered = true;
390 bb.mBuffers.clear();
391 }
392}
393
394void CameraDeviceSession::ResultBatcher::sendBatchMetadataLocked(
395 std::shared_ptr<InflightBatch> batch, uint32_t lastPartialResultIdx) {
396 if (lastPartialResultIdx <= batch->mPartialResultProgress) {
397 // Result has been delivered. Return
398 ALOGW("%s: partial result %u has been delivered", __FUNCTION__, lastPartialResultIdx);
399 return;
400 }
401
402 std::vector<CaptureResult> results;
403 std::vector<uint32_t> toBeRemovedIdxes;
404 for (auto& pair : batch->mResultMds) {
405 uint32_t partialIdx = pair.first;
406 if (partialIdx > lastPartialResultIdx) {
407 continue;
408 }
409 toBeRemovedIdxes.push_back(partialIdx);
410 InflightBatch::MetadataBatch& mb = pair.second;
411 for (const auto& p : mb.mMds) {
412 CaptureResult result;
413 result.frameNumber = p.first;
414 result.result = std::move(p.second);
Yifan Hong993e3d02017-04-12 16:31:23 -0700415 result.fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800416 result.inputBuffer.streamId = -1;
417 result.inputBuffer.bufferId = 0;
418 result.inputBuffer.buffer = nullptr;
419 result.partialResult = partialIdx;
420 results.push_back(std::move(result));
421 }
422 mb.mMds.clear();
423 }
Yifan Hong993e3d02017-04-12 16:31:23 -0700424 hidl_vec<CaptureResult> hResults;
425 hResults.setToExternal(results.data(), results.size());
426 invokeProcessCaptureResultCallback(hResults, /* tryWriteFmq */true);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800427 batch->mPartialResultProgress = lastPartialResultIdx;
428 for (uint32_t partialIdx : toBeRemovedIdxes) {
429 batch->mResultMds.erase(partialIdx);
430 }
431}
432
433void CameraDeviceSession::ResultBatcher::notifySingleMsg(NotifyMsg& msg) {
434 mCallback->notify({msg});
435 return;
436}
437
438void CameraDeviceSession::ResultBatcher::notify(NotifyMsg& msg) {
439 uint32_t frameNumber;
440 if (CC_LIKELY(msg.type == MsgType::SHUTTER)) {
441 frameNumber = msg.msg.shutter.frameNumber;
442 } else {
443 frameNumber = msg.msg.error.frameNumber;
444 }
445
446 auto pair = getBatch(frameNumber);
447 int batchIdx = pair.first;
448 if (batchIdx == NOT_BATCHED) {
449 notifySingleMsg(msg);
450 return;
451 }
452
453 // When error happened, stop batching for all batches earlier
454 if (CC_UNLIKELY(msg.type == MsgType::ERROR)) {
455 Mutex::Autolock _l(mLock);
456 for (int i = 0; i <= batchIdx; i++) {
457 // Send batched data up
458 std::shared_ptr<InflightBatch> batch = mInflightBatches[0];
459 {
460 Mutex::Autolock _l(batch->mLock);
461 sendBatchShutterCbsLocked(batch);
462 sendBatchBuffersLocked(batch);
463 sendBatchMetadataLocked(batch, mNumPartialResults);
464 if (!batch->allDelivered()) {
465 ALOGE("%s: error: some batch data not sent back to framework!",
466 __FUNCTION__);
467 }
468 batch->mRemoved = true;
469 }
470 mInflightBatches.pop_front();
471 }
472 // Send the error up
473 notifySingleMsg(msg);
474 return;
475 }
476 // Queue shutter callbacks for future delivery
477 std::shared_ptr<InflightBatch> batch = pair.second;
478 {
479 Mutex::Autolock _l(batch->mLock);
480 // Check if the batch is removed (mostly by notify error) before lock was acquired
481 if (batch->mRemoved) {
482 // Fall back to non-batch path
483 notifySingleMsg(msg);
484 return;
485 }
486
487 batch->mShutterMsgs.push_back(msg);
488 if (frameNumber == batch->mLastFrame) {
489 sendBatchShutterCbsLocked(batch);
490 }
491 } // end of batch lock scope
492
493 // see if the batch is complete
494 if (frameNumber == batch->mLastFrame) {
495 checkAndRemoveFirstBatch();
496 }
497}
498
Yifan Hong993e3d02017-04-12 16:31:23 -0700499void CameraDeviceSession::ResultBatcher::invokeProcessCaptureResultCallback(
500 hidl_vec<CaptureResult> &results, bool tryWriteFmq) {
501 if (mProcessCaptureResultLock.tryLock() != OK) {
502 ALOGW("%s: previous call is not finished! waiting 1s...",
503 __FUNCTION__);
504 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
505 ALOGE("%s: cannot acquire lock in 1s, cannot proceed",
506 __FUNCTION__);
507 return;
508 }
509 }
510 if (tryWriteFmq && mResultMetadataQueue->availableToWrite() > 0) {
511 for (CaptureResult &result : results) {
512 if (result.result.size() > 0) {
513 if (mResultMetadataQueue->write(result.result.data(), result.result.size())) {
514 result.fmqResultSize = result.result.size();
515 result.result.resize(0);
516 } else {
517 ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
518 result.fmqResultSize = 0;
519 }
520 }
521 }
522 }
523 mCallback->processCaptureResult(results);
524 mProcessCaptureResultLock.unlock();
525}
526
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800527void CameraDeviceSession::ResultBatcher::processOneCaptureResult(CaptureResult& result) {
528 hidl_vec<CaptureResult> results = {result};
Yifan Hong993e3d02017-04-12 16:31:23 -0700529 invokeProcessCaptureResultCallback(results, /* tryWriteFmq */true);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800530 freeReleaseFences(results);
531 return;
532}
533
534void CameraDeviceSession::ResultBatcher::processCaptureResult(CaptureResult& result) {
535 auto pair = getBatch(result.frameNumber);
536 int batchIdx = pair.first;
537 if (batchIdx == NOT_BATCHED) {
538 processOneCaptureResult(result);
539 return;
540 }
541 std::shared_ptr<InflightBatch> batch = pair.second;
542 {
543 Mutex::Autolock _l(batch->mLock);
544 // Check if the batch is removed (mostly by notify error) before lock was acquired
545 if (batch->mRemoved) {
546 // Fall back to non-batch path
547 processOneCaptureResult(result);
548 return;
549 }
550
551 // queue metadata
552 if (result.result.size() != 0) {
553 // Save a copy of metadata
554 batch->mResultMds[result.partialResult].mMds.push_back(
555 std::make_pair(result.frameNumber, result.result));
556 }
557
558 // queue buffer
559 std::vector<int> filledStreams;
560 std::vector<StreamBuffer> nonBatchedBuffers;
561 for (auto& buffer : result.outputBuffers) {
562 auto it = batch->mBatchBufs.find(buffer.streamId);
563 if (it != batch->mBatchBufs.end()) {
564 InflightBatch::BufferBatch& bb = it->second;
565 bb.mBuffers.push_back(buffer);
566 filledStreams.push_back(buffer.streamId);
567 } else {
568 nonBatchedBuffers.push_back(buffer);
569 }
570 }
571
572 // send non-batched buffers up
573 if (nonBatchedBuffers.size() > 0 || result.inputBuffer.streamId != -1) {
574 CaptureResult nonBatchedResult;
575 nonBatchedResult.frameNumber = result.frameNumber;
Yifan Hong993e3d02017-04-12 16:31:23 -0700576 nonBatchedResult.fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800577 nonBatchedResult.outputBuffers = nonBatchedBuffers;
578 nonBatchedResult.inputBuffer = result.inputBuffer;
579 nonBatchedResult.partialResult = 0; // 0 for buffer only results
580 processOneCaptureResult(nonBatchedResult);
581 }
582
583 if (result.frameNumber == batch->mLastFrame) {
584 // Send data up
585 if (result.partialResult > 0) {
586 sendBatchMetadataLocked(batch, result.partialResult);
587 }
588 // send buffer up
589 if (filledStreams.size() > 0) {
590 sendBatchBuffersLocked(batch, filledStreams);
591 }
592 }
593 } // end of batch lock scope
594
595 // see if the batch is complete
596 if (result.frameNumber == batch->mLastFrame) {
597 checkAndRemoveFirstBatch();
598 }
599}
600
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700601// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
602Return<void> CameraDeviceSession::constructDefaultRequestSettings(
603 RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) {
604 Status status = initStatus();
605 CameraMetadata outMetadata;
606 const camera_metadata_t *rawRequest;
607 if (status == Status::OK) {
608 ATRACE_BEGIN("camera3->construct_default_request_settings");
609 rawRequest = mDevice->ops->construct_default_request_settings(mDevice, (int) type);
610 ATRACE_END();
611 if (rawRequest == nullptr) {
612 ALOGI("%s: template %d is not supported on this camera device",
613 __FUNCTION__, type);
614 status = Status::ILLEGAL_ARGUMENT;
615 } else {
616 convertToHidl(rawRequest, &outMetadata);
617 }
618 }
619 _hidl_cb(status, outMetadata);
620 return Void();
621}
622
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100623/**
624 * Map Android N dataspace definitions back to Android M definitions, for
625 * use with HALv3.3 or older.
626 *
627 * Only map where correspondences exist, and otherwise preserve the value.
628 */
629android_dataspace CameraDeviceSession::mapToLegacyDataspace(
630 android_dataspace dataSpace) const {
631 if (mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_3) {
632 switch (dataSpace) {
633 case HAL_DATASPACE_V0_SRGB_LINEAR:
634 return HAL_DATASPACE_SRGB_LINEAR;
635 case HAL_DATASPACE_V0_SRGB:
636 return HAL_DATASPACE_SRGB;
637 case HAL_DATASPACE_V0_JFIF:
638 return HAL_DATASPACE_JFIF;
639 case HAL_DATASPACE_V0_BT601_625:
640 return HAL_DATASPACE_BT601_625;
641 case HAL_DATASPACE_V0_BT601_525:
642 return HAL_DATASPACE_BT601_525;
643 case HAL_DATASPACE_V0_BT709:
644 return HAL_DATASPACE_BT709;
645 default:
646 return dataSpace;
647 }
648 }
649
650 return dataSpace;
651}
652
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700653Return<void> CameraDeviceSession::configureStreams(
654 const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) {
655 Status status = initStatus();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800656 HalStreamConfiguration outStreams;
657
658 // hold the inflight lock for entire configureStreams scope since there must not be any
659 // inflight request/results during stream configuration.
660 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700661 if (!mInflightBuffers.empty()) {
662 ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
663 __FUNCTION__, mInflightBuffers.size());
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800664 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
665 return Void();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700666 }
667
Emilian Peev98014ff2017-02-02 16:20:12 +0000668 if (status != Status::OK) {
669 _hidl_cb(status, outStreams);
670 return Void();
671 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800672
Emilian Peev98014ff2017-02-02 16:20:12 +0000673 camera3_stream_configuration_t stream_list;
674 hidl_vec<camera3_stream_t*> streams;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800675
Emilian Peev98014ff2017-02-02 16:20:12 +0000676 stream_list.operation_mode = (uint32_t) requestedConfiguration.operationMode;
677 stream_list.num_streams = requestedConfiguration.streams.size();
678 streams.resize(stream_list.num_streams);
679 stream_list.streams = streams.data();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700680
Emilian Peev98014ff2017-02-02 16:20:12 +0000681 for (uint32_t i = 0; i < stream_list.num_streams; i++) {
682 int id = requestedConfiguration.streams[i].id;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700683
Emilian Peev98014ff2017-02-02 16:20:12 +0000684 if (mStreamMap.count(id) == 0) {
685 Camera3Stream stream;
686 convertFromHidl(requestedConfiguration.streams[i], &stream);
687 mStreamMap[id] = stream;
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100688 mStreamMap[id].data_space = mapToLegacyDataspace(
689 mStreamMap[id].data_space);
Emilian Peev98014ff2017-02-02 16:20:12 +0000690 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
691 } else {
692 // width/height/format must not change, but usage/rotation might need to change
693 if (mStreamMap[id].stream_type !=
694 (int) requestedConfiguration.streams[i].streamType ||
695 mStreamMap[id].width != requestedConfiguration.streams[i].width ||
696 mStreamMap[id].height != requestedConfiguration.streams[i].height ||
697 mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100698 mStreamMap[id].data_space !=
699 mapToLegacyDataspace( static_cast<android_dataspace_t> (
700 requestedConfiguration.streams[i].dataSpace))) {
Emilian Peev98014ff2017-02-02 16:20:12 +0000701 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
702 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
703 return Void();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800704 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000705 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].rotation;
Yin-Chia Yehc25c54f2017-04-04 13:00:35 -0700706 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].usage;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700707 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000708 streams[i] = &mStreamMap[id];
709 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700710
Emilian Peev98014ff2017-02-02 16:20:12 +0000711 ATRACE_BEGIN("camera3->configure_streams");
712 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
713 ATRACE_END();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700714
Emilian Peev98014ff2017-02-02 16:20:12 +0000715 // In case Hal returns error most likely it was not able to release
716 // the corresponding resources of the deleted streams.
717 if (ret == OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800718 // delete unused streams, note we do this after adding new streams to ensure new stream
719 // will not have the same address as deleted stream, and HAL has a chance to reference
720 // the to be deleted stream in configure_streams call
721 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
722 int id = it->first;
723 bool found = false;
724 for (const auto& stream : requestedConfiguration.streams) {
725 if (id == stream.id) {
726 found = true;
727 break;
728 }
729 }
730 if (!found) {
731 // Unmap all buffers of deleted stream
Emilian Peev98014ff2017-02-02 16:20:12 +0000732 // in case the configuration call succeeds and HAL
733 // is able to release the corresponding resources too.
734 cleanupBuffersLocked(id);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800735 it = mStreamMap.erase(it);
736 } else {
737 ++it;
738 }
739 }
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800740
741 // Track video streams
742 mVideoStreamIds.clear();
743 for (const auto& stream : requestedConfiguration.streams) {
744 if (stream.streamType == StreamType::OUTPUT &&
Chia-I Wu79d13ff2017-03-31 12:48:11 -0700745 stream.usage &
746 graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800747 mVideoStreamIds.push_back(stream.id);
748 }
749 }
750 mResultBatcher.setBatchedStreams(mVideoStreamIds);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700751 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000752
753 if (ret == -EINVAL) {
754 status = Status::ILLEGAL_ARGUMENT;
755 } else if (ret != OK) {
756 status = Status::INTERNAL_ERROR;
757 } else {
758 convertToHidl(stream_list, &outStreams);
759 }
760
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700761 _hidl_cb(status, outStreams);
762 return Void();
763}
764
Emilian Peev98014ff2017-02-02 16:20:12 +0000765// Needs to get called after acquiring 'mInflightLock'
766void CameraDeviceSession::cleanupBuffersLocked(int id) {
767 for (auto& pair : mCirculatingBuffers.at(id)) {
768 sHandleImporter.freeBuffer(pair.second);
769 }
770 mCirculatingBuffers[id].clear();
771 mCirculatingBuffers.erase(id);
772}
773
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -0700774void CameraDeviceSession::updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove) {
775 Mutex::Autolock _l(mInflightLock);
776 for (auto& cache : cachesToRemove) {
777 auto cbsIt = mCirculatingBuffers.find(cache.streamId);
778 if (cbsIt == mCirculatingBuffers.end()) {
779 // The stream could have been removed
780 continue;
781 }
782 CirculatingBuffers& cbs = cbsIt->second;
783 auto it = cbs.find(cache.bufferId);
784 if (it != cbs.end()) {
785 sHandleImporter.freeBuffer(it->second);
786 cbs.erase(it);
787 } else {
788 ALOGE("%s: stream %d buffer %" PRIu64 " is not cached",
789 __FUNCTION__, cache.streamId, cache.bufferId);
790 }
791 }
792}
793
Yifan Hong1192e1d2017-04-11 14:45:00 -0700794Return<void> CameraDeviceSession::getCaptureRequestMetadataQueue(
795 getCaptureRequestMetadataQueue_cb _hidl_cb) {
796 _hidl_cb(*mRequestMetadataQueue->getDesc());
797 return Void();
798}
799
Yifan Hong993e3d02017-04-12 16:31:23 -0700800Return<void> CameraDeviceSession::getCaptureResultMetadataQueue(
801 getCaptureResultMetadataQueue_cb _hidl_cb) {
802 _hidl_cb(*mResultMetadataQueue->getDesc());
803 return Void();
804}
805
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800806Return<void> CameraDeviceSession::processCaptureRequest(
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -0700807 const hidl_vec<CaptureRequest>& requests,
808 const hidl_vec<BufferCache>& cachesToRemove,
809 processCaptureRequest_cb _hidl_cb) {
810 updateBufferCaches(cachesToRemove);
811
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800812 uint32_t numRequestProcessed = 0;
813 Status s = Status::OK;
814 for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
815 s = processOneCaptureRequest(requests[i]);
816 if (s != Status::OK) {
817 break;
818 }
819 }
820
821 if (s == Status::OK && requests.size() > 1) {
822 mResultBatcher.registerBatch(requests);
823 }
824
825 _hidl_cb(s, numRequestProcessed);
826 return Void();
827}
828
829Status CameraDeviceSession::processOneCaptureRequest(const CaptureRequest& request) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700830 Status status = initStatus();
831 if (status != Status::OK) {
832 ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
833 return status;
834 }
835
836 camera3_capture_request_t halRequest;
837 halRequest.frame_number = request.frameNumber;
Yifan Hong1192e1d2017-04-11 14:45:00 -0700838
839 bool converted = true;
840 CameraMetadata settingsFmq; // settings from FMQ
841 if (request.fmqSettingsSize > 0) {
842 // non-blocking read; client must write metadata before calling
843 // processOneCaptureRequest
844 settingsFmq.resize(request.fmqSettingsSize);
845 bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.fmqSettingsSize);
846 if (read) {
847 converted = convertFromHidl(settingsFmq, &halRequest.settings);
848 } else {
849 ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__);
850 converted = false;
851 }
852 } else {
853 converted = convertFromHidl(request.settings, &halRequest.settings);
854 }
855
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700856 if (!converted) {
857 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
858 return Status::INTERNAL_ERROR;
859 }
860
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800861 hidl_vec<buffer_handle_t*> allBufPtrs;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700862 hidl_vec<int> allFences;
863 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800864 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700865 size_t numOutputBufs = request.outputBuffers.size();
866 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800867 status = importRequest(request, allBufPtrs, allFences);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700868 if (status != Status::OK) {
869 return status;
870 }
871
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700872 hidl_vec<camera3_stream_buffer_t> outHalBufs;
873 outHalBufs.resize(numOutputBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800874 {
875 Mutex::Autolock _l(mInflightLock);
876 if (hasInputBuf) {
877 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
878 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
879 convertFromHidl(
880 allBufPtrs[numOutputBufs], request.inputBuffer.status,
881 &mStreamMap[request.inputBuffer.streamId], allFences[numOutputBufs],
882 &bufCache);
883 halRequest.input_buffer = &bufCache;
884 } else {
885 halRequest.input_buffer = nullptr;
886 }
887
888 halRequest.num_output_buffers = numOutputBufs;
889 for (size_t i = 0; i < numOutputBufs; i++) {
890 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
891 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
892 convertFromHidl(
893 allBufPtrs[i], request.outputBuffers[i].status,
894 &mStreamMap[request.outputBuffers[i].streamId], allFences[i],
895 &bufCache);
896 outHalBufs[i] = bufCache;
897 }
898 halRequest.output_buffers = outHalBufs.data();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700899 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700900
901 ATRACE_ASYNC_BEGIN("frame capture", request.frameNumber);
902 ATRACE_BEGIN("camera3->process_capture_request");
903 status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
904 ATRACE_END();
905 if (ret != OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800906 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700907 ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
908
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800909 cleanupInflightFences(allFences, numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700910 if (hasInputBuf) {
911 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
912 mInflightBuffers.erase(key);
913 }
914 for (size_t i = 0; i < numOutputBufs; i++) {
915 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
916 mInflightBuffers.erase(key);
917 }
918 return Status::INTERNAL_ERROR;
919 }
920
921 return Status::OK;
922}
923
924Return<Status> CameraDeviceSession::flush() {
925 Status status = initStatus();
926 if (status == Status::OK) {
927 // Flush is always supported on device 3.1 or later
928 status_t ret = mDevice->ops->flush(mDevice);
929 if (ret != OK) {
930 status = Status::INTERNAL_ERROR;
931 }
932 }
933 return status;
934}
935
936Return<void> CameraDeviceSession::close() {
937 Mutex::Autolock _l(mStateLock);
938 if (!mClosed) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800939 {
940 Mutex::Autolock _l(mInflightLock);
941 if (!mInflightBuffers.empty()) {
942 ALOGE("%s: trying to close while there are still %zu inflight buffers!",
943 __FUNCTION__, mInflightBuffers.size());
944 }
945 }
946
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700947 ATRACE_BEGIN("camera3->close");
948 mDevice->common.close(&mDevice->common);
949 ATRACE_END();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800950
951 // free all imported buffers
952 for(auto& pair : mCirculatingBuffers) {
953 CirculatingBuffers& buffers = pair.second;
954 for (auto& p2 : buffers) {
955 sHandleImporter.freeBuffer(p2.second);
956 }
957 }
958
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700959 mClosed = true;
960 }
961 return Void();
962}
963
964/**
965 * Static callback forwarding methods from HAL to instance
966 */
967void CameraDeviceSession::sProcessCaptureResult(
968 const camera3_callback_ops *cb,
969 const camera3_capture_result *hal_result) {
970 CameraDeviceSession *d =
971 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
972
973 uint32_t frameNumber = hal_result->frame_number;
974 bool hasInputBuf = (hal_result->input_buffer != nullptr);
975 size_t numOutputBufs = hal_result->num_output_buffers;
976 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800977 if (numBufs > 0) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800978 Mutex::Autolock _l(d->mInflightLock);
979 if (hasInputBuf) {
980 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
981 // validate if buffer is inflight
982 auto key = std::make_pair(streamId, frameNumber);
983 if (d->mInflightBuffers.count(key) != 1) {
984 ALOGE("%s: input buffer for stream %d frame %d is not inflight!",
985 __FUNCTION__, streamId, frameNumber);
986 return;
987 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700988 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700989
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800990 for (size_t i = 0; i < numOutputBufs; i++) {
991 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
992 // validate if buffer is inflight
993 auto key = std::make_pair(streamId, frameNumber);
994 if (d->mInflightBuffers.count(key) != 1) {
995 ALOGE("%s: output buffer for stream %d frame %d is not inflight!",
996 __FUNCTION__, streamId, frameNumber);
997 return;
998 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700999 }
1000 }
1001 // We don't need to validate/import fences here since we will be passing them to camera service
1002 // within the scope of this function
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001003 CaptureResult result;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001004 result.frameNumber = frameNumber;
Yifan Hong993e3d02017-04-12 16:31:23 -07001005 result.fmqResultSize = 0;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001006 result.partialResult = hal_result->partial_result;
1007 convertToHidl(hal_result->result, &result.result);
1008 if (hasInputBuf) {
1009 result.inputBuffer.streamId =
1010 static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1011 result.inputBuffer.buffer = nullptr;
1012 result.inputBuffer.status = (BufferStatus) hal_result->input_buffer->status;
1013 // skip acquire fence since it's no use to camera service
1014 if (hal_result->input_buffer->release_fence != -1) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001015 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
1016 handle->data[0] = hal_result->input_buffer->release_fence;
1017 result.inputBuffer.releaseFence = handle;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001018 } else {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001019 result.inputBuffer.releaseFence = nullptr;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001020 }
1021 } else {
1022 result.inputBuffer.streamId = -1;
1023 }
1024
1025 result.outputBuffers.resize(numOutputBufs);
1026 for (size_t i = 0; i < numOutputBufs; i++) {
1027 result.outputBuffers[i].streamId =
1028 static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1029 result.outputBuffers[i].buffer = nullptr;
1030 result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
1031 // skip acquire fence since it's of no use to camera service
1032 if (hal_result->output_buffers[i].release_fence != -1) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001033 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
1034 handle->data[0] = hal_result->output_buffers[i].release_fence;
1035 result.outputBuffers[i].releaseFence = handle;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001036 } else {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001037 result.outputBuffers[i].releaseFence = nullptr;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001038 }
1039 }
1040
1041 // Free inflight record/fences.
1042 // Do this before call back to camera service because camera service might jump to
1043 // configure_streams right after the processCaptureResult call so we need to finish
1044 // updating inflight queues first
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001045 if (numBufs > 0) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001046 Mutex::Autolock _l(d->mInflightLock);
1047 if (hasInputBuf) {
1048 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1049 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001050 d->mInflightBuffers.erase(key);
1051 }
1052
1053 for (size_t i = 0; i < numOutputBufs; i++) {
1054 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1055 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001056 d->mInflightBuffers.erase(key);
1057 }
1058
1059 if (d->mInflightBuffers.empty()) {
1060 ALOGV("%s: inflight buffer queue is now empty!", __FUNCTION__);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001061 }
1062 }
1063
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001064 d->mResultBatcher.processCaptureResult(result);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001065}
1066
1067void CameraDeviceSession::sNotify(
1068 const camera3_callback_ops *cb,
1069 const camera3_notify_msg *msg) {
1070 CameraDeviceSession *d =
1071 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
1072 NotifyMsg hidlMsg;
1073 convertToHidl(msg, &hidlMsg);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001074
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001075 if (hidlMsg.type == (MsgType) CAMERA3_MSG_ERROR &&
1076 hidlMsg.msg.error.errorStreamId != -1) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001077 if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
1078 ALOGE("%s: unknown stream ID %d reports an error!",
1079 __FUNCTION__, hidlMsg.msg.error.errorStreamId);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001080 return;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001081 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001082 }
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001083 d->mResultBatcher.notify(hidlMsg);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001084}
1085
1086} // namespace implementation
1087} // namespace V3_2
1088} // namespace device
1089} // namespace camera
1090} // namespace hardware
1091} // namespace android