blob: 82d167a4732bd790a4329ee32af048b62d937615 [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 Yeh519c1672017-04-21 14:59:31 -070038HandleImporter CameraDeviceSession::sHandleImporter;
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),
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080047 mResultBatcher(callback) {
48
49 mDeviceInfo = deviceInfo;
50 uint32_t numPartialResults = 1;
51 camera_metadata_entry partialResultsCount =
52 mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
53 if (partialResultsCount.count > 0) {
54 numPartialResults = partialResultsCount.data.i32[0];
55 }
56 mResultBatcher.setNumPartialResults(numPartialResults);
57
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070058 mInitFail = initialize();
59}
60
61bool CameraDeviceSession::initialize() {
62 /** Initialize device with callback functions */
63 ATRACE_BEGIN("camera3->initialize");
64 status_t res = mDevice->ops->initialize(mDevice, this);
65 ATRACE_END();
66
67 if (res != OK) {
68 ALOGE("%s: Unable to initialize HAL device: %s (%d)",
69 __FUNCTION__, strerror(-res), res);
70 mDevice->common.close(&mDevice->common);
71 mClosed = true;
72 return true;
73 }
Yifan Hong1192e1d2017-04-11 14:45:00 -070074
75 mRequestMetadataQueue = std::make_unique<RequestMetadataQueue>(
76 CAMERA_REQUEST_METADATA_QUEUE_SIZE, false /* non blocking */);
77 if (!mRequestMetadataQueue->isValid()) {
Yifan Hong993e3d02017-04-12 16:31:23 -070078 ALOGE("%s: invalid request fmq", __FUNCTION__);
Yifan Hong1192e1d2017-04-11 14:45:00 -070079 return true;
80 }
Yifan Hong993e3d02017-04-12 16:31:23 -070081 mResultMetadataQueue = std::make_shared<RequestMetadataQueue>(
82 CAMERA_RESULT_METADATA_QUEUE_SIZE, false /* non blocking */);
83 if (!mResultMetadataQueue->isValid()) {
84 ALOGE("%s: invalid result fmq", __FUNCTION__);
85 return true;
86 }
87 mResultBatcher.setResultMetadataQueue(mResultMetadataQueue);
Yifan Hong1192e1d2017-04-11 14:45:00 -070088
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070089 return false;
90}
91
92CameraDeviceSession::~CameraDeviceSession() {
93 if (!isClosed()) {
94 ALOGE("CameraDeviceSession deleted before close!");
95 close();
96 }
97}
98
99bool CameraDeviceSession::isClosed() {
100 Mutex::Autolock _l(mStateLock);
101 return mClosed;
102}
103
104Status CameraDeviceSession::initStatus() const {
105 Mutex::Autolock _l(mStateLock);
106 Status status = Status::OK;
107 if (mInitFail) {
108 status = Status::INTERNAL_ERROR;
109 } else if (mDisconnected) {
110 status = Status::CAMERA_DISCONNECTED;
111 } else if (mClosed) {
112 status = Status::INTERNAL_ERROR;
113 }
114 return status;
115}
116
117void CameraDeviceSession::disconnect() {
118 Mutex::Autolock _l(mStateLock);
119 mDisconnected = true;
120 ALOGW("%s: Camera device is disconnected. Closing.", __FUNCTION__);
121 if (!mClosed) {
122 mDevice->common.close(&mDevice->common);
123 mClosed = true;
124 }
125}
126
127void CameraDeviceSession::dumpState(const native_handle_t* fd) {
128 if (!isClosed()) {
129 mDevice->ops->dump(mDevice, fd->data[0]);
130 }
131}
132
133Status CameraDeviceSession::importRequest(
134 const CaptureRequest& request,
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800135 hidl_vec<buffer_handle_t*>& allBufPtrs,
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700136 hidl_vec<int>& allFences) {
137 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800138 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700139 size_t numOutputBufs = request.outputBuffers.size();
140 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
141 // Validate all I/O buffers
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800142 hidl_vec<buffer_handle_t> allBufs;
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800143 hidl_vec<uint64_t> allBufIds;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700144 allBufs.resize(numBufs);
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800145 allBufIds.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800146 allBufPtrs.resize(numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700147 allFences.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800148 std::vector<int32_t> streamIds(numBufs);
149
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700150 for (size_t i = 0; i < numOutputBufs; i++) {
151 allBufs[i] = request.outputBuffers[i].buffer.getNativeHandle();
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800152 allBufIds[i] = request.outputBuffers[i].bufferId;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800153 allBufPtrs[i] = &allBufs[i];
154 streamIds[i] = request.outputBuffers[i].streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700155 }
156 if (hasInputBuf) {
157 allBufs[numOutputBufs] = request.inputBuffer.buffer.getNativeHandle();
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800158 allBufIds[numOutputBufs] = request.inputBuffer.bufferId;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800159 allBufPtrs[numOutputBufs] = &allBufs[numOutputBufs];
160 streamIds[numOutputBufs] = request.inputBuffer.streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700161 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800162
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700163 for (size_t i = 0; i < numBufs; i++) {
164 buffer_handle_t buf = allBufs[i];
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800165 uint64_t bufId = allBufIds[i];
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800166 CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]];
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800167 if (cbs.count(bufId) == 0) {
168 if (buf == nullptr) {
169 ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
170 return Status::ILLEGAL_ARGUMENT;
171 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800172 // Register a newly seen buffer
173 buffer_handle_t importedBuf = buf;
174 sHandleImporter.importBuffer(importedBuf);
175 if (importedBuf == nullptr) {
176 ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i);
177 return Status::INTERNAL_ERROR;
178 } else {
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800179 cbs[bufId] = importedBuf;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800180 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700181 }
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800182 allBufPtrs[i] = &cbs[bufId];
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700183 }
184
185 // All buffers are imported. Now validate output buffer acquire fences
186 for (size_t i = 0; i < numOutputBufs; i++) {
187 if (!sHandleImporter.importFence(
188 request.outputBuffers[i].acquireFence, allFences[i])) {
189 ALOGE("%s: output buffer %zu acquire fence is invalid", __FUNCTION__, i);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800190 cleanupInflightFences(allFences, i);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700191 return Status::INTERNAL_ERROR;
192 }
193 }
194
195 // Validate input buffer acquire fences
196 if (hasInputBuf) {
197 if (!sHandleImporter.importFence(
198 request.inputBuffer.acquireFence, allFences[numOutputBufs])) {
199 ALOGE("%s: input buffer acquire fence is invalid", __FUNCTION__);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800200 cleanupInflightFences(allFences, numOutputBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700201 return Status::INTERNAL_ERROR;
202 }
203 }
204 return Status::OK;
205}
206
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800207void CameraDeviceSession::cleanupInflightFences(
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700208 hidl_vec<int>& allFences, size_t numFences) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700209 for (size_t j = 0; j < numFences; j++) {
210 sHandleImporter.closeFence(allFences[j]);
211 }
212}
213
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800214CameraDeviceSession::ResultBatcher::ResultBatcher(
215 const sp<ICameraDeviceCallback>& callback) : mCallback(callback) {};
216
217bool CameraDeviceSession::ResultBatcher::InflightBatch::allDelivered() const {
218 if (!mShutterDelivered) return false;
219
220 if (mPartialResultProgress < mNumPartialResults) {
221 return false;
222 }
223
224 for (const auto& pair : mBatchBufs) {
225 if (!pair.second.mDelivered) {
226 return false;
227 }
228 }
229 return true;
230}
231
232void CameraDeviceSession::ResultBatcher::setNumPartialResults(uint32_t n) {
233 Mutex::Autolock _l(mLock);
234 mNumPartialResults = n;
235}
236
237void CameraDeviceSession::ResultBatcher::setBatchedStreams(
238 const std::vector<int>& streamsToBatch) {
239 Mutex::Autolock _l(mLock);
240 mStreamsToBatch = streamsToBatch;
241}
242
Yifan Hong993e3d02017-04-12 16:31:23 -0700243void CameraDeviceSession::ResultBatcher::setResultMetadataQueue(std::shared_ptr<ResultMetadataQueue> q) {
244 Mutex::Autolock _l(mLock);
245 mResultMetadataQueue = q;
246}
247
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800248void CameraDeviceSession::ResultBatcher::registerBatch(
249 const hidl_vec<CaptureRequest>& requests) {
250 auto batch = std::make_shared<InflightBatch>();
251 batch->mFirstFrame = requests[0].frameNumber;
252 batch->mBatchSize = requests.size();
253 batch->mLastFrame = batch->mFirstFrame + batch->mBatchSize - 1;
254 batch->mNumPartialResults = mNumPartialResults;
255 for (int id : mStreamsToBatch) {
256 batch->mBatchBufs[id] = InflightBatch::BufferBatch();
257 }
258 Mutex::Autolock _l(mLock);
259 mInflightBatches.push_back(batch);
260}
261
262std::pair<int, std::shared_ptr<CameraDeviceSession::ResultBatcher::InflightBatch>>
263CameraDeviceSession::ResultBatcher::getBatch(
264 uint32_t frameNumber) {
265 Mutex::Autolock _l(mLock);
266 int numBatches = mInflightBatches.size();
267 if (numBatches == 0) {
268 return std::make_pair(NOT_BATCHED, nullptr);
269 }
270 uint32_t frameMin = mInflightBatches[0]->mFirstFrame;
271 uint32_t frameMax = mInflightBatches[numBatches - 1]->mLastFrame;
272 if (frameNumber < frameMin || frameNumber > frameMax) {
273 return std::make_pair(NOT_BATCHED, nullptr);
274 }
275 for (int i = 0; i < numBatches; i++) {
276 if (frameNumber >= mInflightBatches[i]->mFirstFrame &&
277 frameNumber <= mInflightBatches[i]->mLastFrame) {
278 return std::make_pair(i, mInflightBatches[i]);
279 }
280 }
281 return std::make_pair(NOT_BATCHED, nullptr);
282}
283
284void CameraDeviceSession::ResultBatcher::checkAndRemoveFirstBatch() {
285 Mutex::Autolock _l(mLock);
286 if (mInflightBatches.size() > 0) {
287 std::shared_ptr<InflightBatch> batch = mInflightBatches[0];
288 bool shouldRemove = false;
289 {
290 Mutex::Autolock _l(batch->mLock);
291 if (batch->allDelivered()) {
292 batch->mRemoved = true;
293 shouldRemove = true;
294 }
295 }
296 if (shouldRemove) {
297 mInflightBatches.pop_front();
298 }
299 }
300}
301
302void CameraDeviceSession::ResultBatcher::sendBatchShutterCbsLocked(std::shared_ptr<InflightBatch> batch) {
303 if (batch->mShutterDelivered) {
304 ALOGW("%s: batch shutter callback already sent!", __FUNCTION__);
305 return;
306 }
307
308 mCallback->notify(batch->mShutterMsgs);
309 batch->mShutterDelivered = true;
310 batch->mShutterMsgs.clear();
311}
312
313void CameraDeviceSession::ResultBatcher::freeReleaseFences(hidl_vec<CaptureResult>& results) {
314 for (auto& result : results) {
315 if (result.inputBuffer.releaseFence.getNativeHandle() != nullptr) {
316 native_handle_t* handle = const_cast<native_handle_t*>(
317 result.inputBuffer.releaseFence.getNativeHandle());
318 native_handle_delete(handle);
319 }
320 for (auto& buf : result.outputBuffers) {
321 if (buf.releaseFence.getNativeHandle() != nullptr) {
322 native_handle_t* handle = const_cast<native_handle_t*>(
323 buf.releaseFence.getNativeHandle());
324 native_handle_delete(handle);
325 }
326 }
327 }
328 return;
329}
330
331void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(std::shared_ptr<InflightBatch> batch) {
332 sendBatchBuffersLocked(batch, mStreamsToBatch);
333}
334
335void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(
336 std::shared_ptr<InflightBatch> batch, const std::vector<int>& streams) {
337 size_t batchSize = 0;
338 for (int streamId : streams) {
339 auto it = batch->mBatchBufs.find(streamId);
340 if (it != batch->mBatchBufs.end()) {
341 InflightBatch::BufferBatch& bb = it->second;
342 if (bb.mDelivered) {
343 continue;
344 }
345 if (bb.mBuffers.size() > batchSize) {
346 batchSize = bb.mBuffers.size();
347 }
348 } else {
349 ALOGE("%s: stream ID %d is not batched!", __FUNCTION__, streamId);
350 return;
351 }
352 }
353
354 if (batchSize == 0) {
355 ALOGW("%s: there is no buffer to be delivered for this batch.", __FUNCTION__);
356 for (int streamId : streams) {
357 InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
358 bb.mDelivered = true;
359 }
360 return;
361 }
362
363 hidl_vec<CaptureResult> results;
364 results.resize(batchSize);
365 for (size_t i = 0; i < batchSize; i++) {
366 results[i].frameNumber = batch->mFirstFrame + i;
Yifan Hong993e3d02017-04-12 16:31:23 -0700367 results[i].fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800368 results[i].partialResult = 0; // 0 for buffer only results
369 results[i].inputBuffer.streamId = -1;
370 results[i].inputBuffer.bufferId = 0;
371 results[i].inputBuffer.buffer = nullptr;
372 std::vector<StreamBuffer> outBufs;
373 for (int streamId : streams) {
374 InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
375 if (bb.mDelivered) {
376 continue;
377 }
378 if (i < bb.mBuffers.size()) {
379 outBufs.push_back(bb.mBuffers[i]);
380 }
381 }
382 results[i].outputBuffers = outBufs;
383 }
Yifan Hong993e3d02017-04-12 16:31:23 -0700384 invokeProcessCaptureResultCallback(results, /* tryWriteFmq */false);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800385 freeReleaseFences(results);
386 for (int streamId : streams) {
387 InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
388 bb.mDelivered = true;
389 bb.mBuffers.clear();
390 }
391}
392
393void CameraDeviceSession::ResultBatcher::sendBatchMetadataLocked(
394 std::shared_ptr<InflightBatch> batch, uint32_t lastPartialResultIdx) {
395 if (lastPartialResultIdx <= batch->mPartialResultProgress) {
396 // Result has been delivered. Return
397 ALOGW("%s: partial result %u has been delivered", __FUNCTION__, lastPartialResultIdx);
398 return;
399 }
400
401 std::vector<CaptureResult> results;
402 std::vector<uint32_t> toBeRemovedIdxes;
403 for (auto& pair : batch->mResultMds) {
404 uint32_t partialIdx = pair.first;
405 if (partialIdx > lastPartialResultIdx) {
406 continue;
407 }
408 toBeRemovedIdxes.push_back(partialIdx);
409 InflightBatch::MetadataBatch& mb = pair.second;
410 for (const auto& p : mb.mMds) {
411 CaptureResult result;
412 result.frameNumber = p.first;
413 result.result = std::move(p.second);
Yifan Hong993e3d02017-04-12 16:31:23 -0700414 result.fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800415 result.inputBuffer.streamId = -1;
416 result.inputBuffer.bufferId = 0;
417 result.inputBuffer.buffer = nullptr;
418 result.partialResult = partialIdx;
419 results.push_back(std::move(result));
420 }
421 mb.mMds.clear();
422 }
Yifan Hong993e3d02017-04-12 16:31:23 -0700423 hidl_vec<CaptureResult> hResults;
424 hResults.setToExternal(results.data(), results.size());
425 invokeProcessCaptureResultCallback(hResults, /* tryWriteFmq */true);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800426 batch->mPartialResultProgress = lastPartialResultIdx;
427 for (uint32_t partialIdx : toBeRemovedIdxes) {
428 batch->mResultMds.erase(partialIdx);
429 }
430}
431
432void CameraDeviceSession::ResultBatcher::notifySingleMsg(NotifyMsg& msg) {
433 mCallback->notify({msg});
434 return;
435}
436
437void CameraDeviceSession::ResultBatcher::notify(NotifyMsg& msg) {
438 uint32_t frameNumber;
439 if (CC_LIKELY(msg.type == MsgType::SHUTTER)) {
440 frameNumber = msg.msg.shutter.frameNumber;
441 } else {
442 frameNumber = msg.msg.error.frameNumber;
443 }
444
445 auto pair = getBatch(frameNumber);
446 int batchIdx = pair.first;
447 if (batchIdx == NOT_BATCHED) {
448 notifySingleMsg(msg);
449 return;
450 }
451
452 // When error happened, stop batching for all batches earlier
453 if (CC_UNLIKELY(msg.type == MsgType::ERROR)) {
454 Mutex::Autolock _l(mLock);
455 for (int i = 0; i <= batchIdx; i++) {
456 // Send batched data up
457 std::shared_ptr<InflightBatch> batch = mInflightBatches[0];
458 {
459 Mutex::Autolock _l(batch->mLock);
460 sendBatchShutterCbsLocked(batch);
461 sendBatchBuffersLocked(batch);
462 sendBatchMetadataLocked(batch, mNumPartialResults);
463 if (!batch->allDelivered()) {
464 ALOGE("%s: error: some batch data not sent back to framework!",
465 __FUNCTION__);
466 }
467 batch->mRemoved = true;
468 }
469 mInflightBatches.pop_front();
470 }
471 // Send the error up
472 notifySingleMsg(msg);
473 return;
474 }
475 // Queue shutter callbacks for future delivery
476 std::shared_ptr<InflightBatch> batch = pair.second;
477 {
478 Mutex::Autolock _l(batch->mLock);
479 // Check if the batch is removed (mostly by notify error) before lock was acquired
480 if (batch->mRemoved) {
481 // Fall back to non-batch path
482 notifySingleMsg(msg);
483 return;
484 }
485
486 batch->mShutterMsgs.push_back(msg);
487 if (frameNumber == batch->mLastFrame) {
488 sendBatchShutterCbsLocked(batch);
489 }
490 } // end of batch lock scope
491
492 // see if the batch is complete
493 if (frameNumber == batch->mLastFrame) {
494 checkAndRemoveFirstBatch();
495 }
496}
497
Yifan Hong993e3d02017-04-12 16:31:23 -0700498void CameraDeviceSession::ResultBatcher::invokeProcessCaptureResultCallback(
499 hidl_vec<CaptureResult> &results, bool tryWriteFmq) {
500 if (mProcessCaptureResultLock.tryLock() != OK) {
501 ALOGW("%s: previous call is not finished! waiting 1s...",
502 __FUNCTION__);
503 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
504 ALOGE("%s: cannot acquire lock in 1s, cannot proceed",
505 __FUNCTION__);
506 return;
507 }
508 }
509 if (tryWriteFmq && mResultMetadataQueue->availableToWrite() > 0) {
510 for (CaptureResult &result : results) {
511 if (result.result.size() > 0) {
512 if (mResultMetadataQueue->write(result.result.data(), result.result.size())) {
513 result.fmqResultSize = result.result.size();
514 result.result.resize(0);
515 } else {
516 ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
517 result.fmqResultSize = 0;
518 }
519 }
520 }
521 }
522 mCallback->processCaptureResult(results);
523 mProcessCaptureResultLock.unlock();
524}
525
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800526void CameraDeviceSession::ResultBatcher::processOneCaptureResult(CaptureResult& result) {
527 hidl_vec<CaptureResult> results = {result};
Yifan Hong993e3d02017-04-12 16:31:23 -0700528 invokeProcessCaptureResultCallback(results, /* tryWriteFmq */true);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800529 freeReleaseFences(results);
530 return;
531}
532
533void CameraDeviceSession::ResultBatcher::processCaptureResult(CaptureResult& result) {
534 auto pair = getBatch(result.frameNumber);
535 int batchIdx = pair.first;
536 if (batchIdx == NOT_BATCHED) {
537 processOneCaptureResult(result);
538 return;
539 }
540 std::shared_ptr<InflightBatch> batch = pair.second;
541 {
542 Mutex::Autolock _l(batch->mLock);
543 // Check if the batch is removed (mostly by notify error) before lock was acquired
544 if (batch->mRemoved) {
545 // Fall back to non-batch path
546 processOneCaptureResult(result);
547 return;
548 }
549
550 // queue metadata
551 if (result.result.size() != 0) {
552 // Save a copy of metadata
553 batch->mResultMds[result.partialResult].mMds.push_back(
554 std::make_pair(result.frameNumber, result.result));
555 }
556
557 // queue buffer
558 std::vector<int> filledStreams;
559 std::vector<StreamBuffer> nonBatchedBuffers;
560 for (auto& buffer : result.outputBuffers) {
561 auto it = batch->mBatchBufs.find(buffer.streamId);
562 if (it != batch->mBatchBufs.end()) {
563 InflightBatch::BufferBatch& bb = it->second;
564 bb.mBuffers.push_back(buffer);
565 filledStreams.push_back(buffer.streamId);
566 } else {
567 nonBatchedBuffers.push_back(buffer);
568 }
569 }
570
571 // send non-batched buffers up
572 if (nonBatchedBuffers.size() > 0 || result.inputBuffer.streamId != -1) {
573 CaptureResult nonBatchedResult;
574 nonBatchedResult.frameNumber = result.frameNumber;
Yifan Hong993e3d02017-04-12 16:31:23 -0700575 nonBatchedResult.fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800576 nonBatchedResult.outputBuffers = nonBatchedBuffers;
577 nonBatchedResult.inputBuffer = result.inputBuffer;
578 nonBatchedResult.partialResult = 0; // 0 for buffer only results
579 processOneCaptureResult(nonBatchedResult);
580 }
581
582 if (result.frameNumber == batch->mLastFrame) {
583 // Send data up
584 if (result.partialResult > 0) {
585 sendBatchMetadataLocked(batch, result.partialResult);
586 }
587 // send buffer up
588 if (filledStreams.size() > 0) {
589 sendBatchBuffersLocked(batch, filledStreams);
590 }
591 }
592 } // end of batch lock scope
593
594 // see if the batch is complete
595 if (result.frameNumber == batch->mLastFrame) {
596 checkAndRemoveFirstBatch();
597 }
598}
599
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700600// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
601Return<void> CameraDeviceSession::constructDefaultRequestSettings(
602 RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) {
603 Status status = initStatus();
604 CameraMetadata outMetadata;
605 const camera_metadata_t *rawRequest;
606 if (status == Status::OK) {
607 ATRACE_BEGIN("camera3->construct_default_request_settings");
608 rawRequest = mDevice->ops->construct_default_request_settings(mDevice, (int) type);
609 ATRACE_END();
610 if (rawRequest == nullptr) {
611 ALOGI("%s: template %d is not supported on this camera device",
612 __FUNCTION__, type);
613 status = Status::ILLEGAL_ARGUMENT;
614 } else {
615 convertToHidl(rawRequest, &outMetadata);
616 }
617 }
618 _hidl_cb(status, outMetadata);
619 return Void();
620}
621
622Return<void> CameraDeviceSession::configureStreams(
623 const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) {
624 Status status = initStatus();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800625 HalStreamConfiguration outStreams;
626
627 // hold the inflight lock for entire configureStreams scope since there must not be any
628 // inflight request/results during stream configuration.
629 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700630 if (!mInflightBuffers.empty()) {
631 ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
632 __FUNCTION__, mInflightBuffers.size());
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800633 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
634 return Void();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700635 }
636
Emilian Peev98014ff2017-02-02 16:20:12 +0000637 if (status != Status::OK) {
638 _hidl_cb(status, outStreams);
639 return Void();
640 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800641
Emilian Peev98014ff2017-02-02 16:20:12 +0000642 camera3_stream_configuration_t stream_list;
643 hidl_vec<camera3_stream_t*> streams;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800644
Emilian Peev98014ff2017-02-02 16:20:12 +0000645 stream_list.operation_mode = (uint32_t) requestedConfiguration.operationMode;
646 stream_list.num_streams = requestedConfiguration.streams.size();
647 streams.resize(stream_list.num_streams);
648 stream_list.streams = streams.data();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700649
Emilian Peev98014ff2017-02-02 16:20:12 +0000650 for (uint32_t i = 0; i < stream_list.num_streams; i++) {
651 int id = requestedConfiguration.streams[i].id;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700652
Emilian Peev98014ff2017-02-02 16:20:12 +0000653 if (mStreamMap.count(id) == 0) {
654 Camera3Stream stream;
655 convertFromHidl(requestedConfiguration.streams[i], &stream);
656 mStreamMap[id] = stream;
657 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
658 } else {
659 // width/height/format must not change, but usage/rotation might need to change
660 if (mStreamMap[id].stream_type !=
661 (int) requestedConfiguration.streams[i].streamType ||
662 mStreamMap[id].width != requestedConfiguration.streams[i].width ||
663 mStreamMap[id].height != requestedConfiguration.streams[i].height ||
664 mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
665 mStreamMap[id].data_space != (android_dataspace_t)
666 requestedConfiguration.streams[i].dataSpace) {
667 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
668 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
669 return Void();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800670 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000671 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].rotation;
Yin-Chia Yehc25c54f2017-04-04 13:00:35 -0700672 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].usage;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700673 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000674 streams[i] = &mStreamMap[id];
675 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700676
Emilian Peev98014ff2017-02-02 16:20:12 +0000677 ATRACE_BEGIN("camera3->configure_streams");
678 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
679 ATRACE_END();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700680
Emilian Peev98014ff2017-02-02 16:20:12 +0000681 // In case Hal returns error most likely it was not able to release
682 // the corresponding resources of the deleted streams.
683 if (ret == OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800684 // delete unused streams, note we do this after adding new streams to ensure new stream
685 // will not have the same address as deleted stream, and HAL has a chance to reference
686 // the to be deleted stream in configure_streams call
687 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
688 int id = it->first;
689 bool found = false;
690 for (const auto& stream : requestedConfiguration.streams) {
691 if (id == stream.id) {
692 found = true;
693 break;
694 }
695 }
696 if (!found) {
697 // Unmap all buffers of deleted stream
Emilian Peev98014ff2017-02-02 16:20:12 +0000698 // in case the configuration call succeeds and HAL
699 // is able to release the corresponding resources too.
700 cleanupBuffersLocked(id);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800701 it = mStreamMap.erase(it);
702 } else {
703 ++it;
704 }
705 }
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800706
707 // Track video streams
708 mVideoStreamIds.clear();
709 for (const auto& stream : requestedConfiguration.streams) {
710 if (stream.streamType == StreamType::OUTPUT &&
Chia-I Wu79d13ff2017-03-31 12:48:11 -0700711 stream.usage &
712 graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800713 mVideoStreamIds.push_back(stream.id);
714 }
715 }
716 mResultBatcher.setBatchedStreams(mVideoStreamIds);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700717 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000718
719 if (ret == -EINVAL) {
720 status = Status::ILLEGAL_ARGUMENT;
721 } else if (ret != OK) {
722 status = Status::INTERNAL_ERROR;
723 } else {
724 convertToHidl(stream_list, &outStreams);
725 }
726
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700727 _hidl_cb(status, outStreams);
728 return Void();
729}
730
Emilian Peev98014ff2017-02-02 16:20:12 +0000731// Needs to get called after acquiring 'mInflightLock'
732void CameraDeviceSession::cleanupBuffersLocked(int id) {
733 for (auto& pair : mCirculatingBuffers.at(id)) {
734 sHandleImporter.freeBuffer(pair.second);
735 }
736 mCirculatingBuffers[id].clear();
737 mCirculatingBuffers.erase(id);
738}
739
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -0700740void CameraDeviceSession::updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove) {
741 Mutex::Autolock _l(mInflightLock);
742 for (auto& cache : cachesToRemove) {
743 auto cbsIt = mCirculatingBuffers.find(cache.streamId);
744 if (cbsIt == mCirculatingBuffers.end()) {
745 // The stream could have been removed
746 continue;
747 }
748 CirculatingBuffers& cbs = cbsIt->second;
749 auto it = cbs.find(cache.bufferId);
750 if (it != cbs.end()) {
751 sHandleImporter.freeBuffer(it->second);
752 cbs.erase(it);
753 } else {
754 ALOGE("%s: stream %d buffer %" PRIu64 " is not cached",
755 __FUNCTION__, cache.streamId, cache.bufferId);
756 }
757 }
758}
759
Yifan Hong1192e1d2017-04-11 14:45:00 -0700760Return<void> CameraDeviceSession::getCaptureRequestMetadataQueue(
761 getCaptureRequestMetadataQueue_cb _hidl_cb) {
762 _hidl_cb(*mRequestMetadataQueue->getDesc());
763 return Void();
764}
765
Yifan Hong993e3d02017-04-12 16:31:23 -0700766Return<void> CameraDeviceSession::getCaptureResultMetadataQueue(
767 getCaptureResultMetadataQueue_cb _hidl_cb) {
768 _hidl_cb(*mResultMetadataQueue->getDesc());
769 return Void();
770}
771
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800772Return<void> CameraDeviceSession::processCaptureRequest(
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -0700773 const hidl_vec<CaptureRequest>& requests,
774 const hidl_vec<BufferCache>& cachesToRemove,
775 processCaptureRequest_cb _hidl_cb) {
776 updateBufferCaches(cachesToRemove);
777
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800778 uint32_t numRequestProcessed = 0;
779 Status s = Status::OK;
780 for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
781 s = processOneCaptureRequest(requests[i]);
782 if (s != Status::OK) {
783 break;
784 }
785 }
786
787 if (s == Status::OK && requests.size() > 1) {
788 mResultBatcher.registerBatch(requests);
789 }
790
791 _hidl_cb(s, numRequestProcessed);
792 return Void();
793}
794
795Status CameraDeviceSession::processOneCaptureRequest(const CaptureRequest& request) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700796 Status status = initStatus();
797 if (status != Status::OK) {
798 ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
799 return status;
800 }
801
802 camera3_capture_request_t halRequest;
803 halRequest.frame_number = request.frameNumber;
Yifan Hong1192e1d2017-04-11 14:45:00 -0700804
805 bool converted = true;
806 CameraMetadata settingsFmq; // settings from FMQ
807 if (request.fmqSettingsSize > 0) {
808 // non-blocking read; client must write metadata before calling
809 // processOneCaptureRequest
810 settingsFmq.resize(request.fmqSettingsSize);
811 bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.fmqSettingsSize);
812 if (read) {
813 converted = convertFromHidl(settingsFmq, &halRequest.settings);
814 } else {
815 ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__);
816 converted = false;
817 }
818 } else {
819 converted = convertFromHidl(request.settings, &halRequest.settings);
820 }
821
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700822 if (!converted) {
823 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
824 return Status::INTERNAL_ERROR;
825 }
826
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800827 hidl_vec<buffer_handle_t*> allBufPtrs;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700828 hidl_vec<int> allFences;
829 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800830 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700831 size_t numOutputBufs = request.outputBuffers.size();
832 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800833 status = importRequest(request, allBufPtrs, allFences);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700834 if (status != Status::OK) {
835 return status;
836 }
837
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700838 hidl_vec<camera3_stream_buffer_t> outHalBufs;
839 outHalBufs.resize(numOutputBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800840 {
841 Mutex::Autolock _l(mInflightLock);
842 if (hasInputBuf) {
843 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
844 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
845 convertFromHidl(
846 allBufPtrs[numOutputBufs], request.inputBuffer.status,
847 &mStreamMap[request.inputBuffer.streamId], allFences[numOutputBufs],
848 &bufCache);
849 halRequest.input_buffer = &bufCache;
850 } else {
851 halRequest.input_buffer = nullptr;
852 }
853
854 halRequest.num_output_buffers = numOutputBufs;
855 for (size_t i = 0; i < numOutputBufs; i++) {
856 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
857 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
858 convertFromHidl(
859 allBufPtrs[i], request.outputBuffers[i].status,
860 &mStreamMap[request.outputBuffers[i].streamId], allFences[i],
861 &bufCache);
862 outHalBufs[i] = bufCache;
863 }
864 halRequest.output_buffers = outHalBufs.data();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700865 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700866
867 ATRACE_ASYNC_BEGIN("frame capture", request.frameNumber);
868 ATRACE_BEGIN("camera3->process_capture_request");
869 status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
870 ATRACE_END();
871 if (ret != OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800872 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700873 ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
874
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800875 cleanupInflightFences(allFences, numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700876 if (hasInputBuf) {
877 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
878 mInflightBuffers.erase(key);
879 }
880 for (size_t i = 0; i < numOutputBufs; i++) {
881 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
882 mInflightBuffers.erase(key);
883 }
884 return Status::INTERNAL_ERROR;
885 }
886
887 return Status::OK;
888}
889
890Return<Status> CameraDeviceSession::flush() {
891 Status status = initStatus();
892 if (status == Status::OK) {
893 // Flush is always supported on device 3.1 or later
894 status_t ret = mDevice->ops->flush(mDevice);
895 if (ret != OK) {
896 status = Status::INTERNAL_ERROR;
897 }
898 }
899 return status;
900}
901
902Return<void> CameraDeviceSession::close() {
903 Mutex::Autolock _l(mStateLock);
904 if (!mClosed) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800905 {
906 Mutex::Autolock _l(mInflightLock);
907 if (!mInflightBuffers.empty()) {
908 ALOGE("%s: trying to close while there are still %zu inflight buffers!",
909 __FUNCTION__, mInflightBuffers.size());
910 }
911 }
912
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700913 ATRACE_BEGIN("camera3->close");
914 mDevice->common.close(&mDevice->common);
915 ATRACE_END();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800916
917 // free all imported buffers
918 for(auto& pair : mCirculatingBuffers) {
919 CirculatingBuffers& buffers = pair.second;
920 for (auto& p2 : buffers) {
921 sHandleImporter.freeBuffer(p2.second);
922 }
923 }
924
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700925 mClosed = true;
926 }
927 return Void();
928}
929
930/**
931 * Static callback forwarding methods from HAL to instance
932 */
933void CameraDeviceSession::sProcessCaptureResult(
934 const camera3_callback_ops *cb,
935 const camera3_capture_result *hal_result) {
936 CameraDeviceSession *d =
937 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
938
939 uint32_t frameNumber = hal_result->frame_number;
940 bool hasInputBuf = (hal_result->input_buffer != nullptr);
941 size_t numOutputBufs = hal_result->num_output_buffers;
942 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800943 if (numBufs > 0) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800944 Mutex::Autolock _l(d->mInflightLock);
945 if (hasInputBuf) {
946 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
947 // validate if buffer is inflight
948 auto key = std::make_pair(streamId, frameNumber);
949 if (d->mInflightBuffers.count(key) != 1) {
950 ALOGE("%s: input buffer for stream %d frame %d is not inflight!",
951 __FUNCTION__, streamId, frameNumber);
952 return;
953 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700954 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700955
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800956 for (size_t i = 0; i < numOutputBufs; i++) {
957 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
958 // validate if buffer is inflight
959 auto key = std::make_pair(streamId, frameNumber);
960 if (d->mInflightBuffers.count(key) != 1) {
961 ALOGE("%s: output buffer for stream %d frame %d is not inflight!",
962 __FUNCTION__, streamId, frameNumber);
963 return;
964 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700965 }
966 }
967 // We don't need to validate/import fences here since we will be passing them to camera service
968 // within the scope of this function
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700969 CaptureResult result;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700970 result.frameNumber = frameNumber;
Yifan Hong993e3d02017-04-12 16:31:23 -0700971 result.fmqResultSize = 0;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700972 result.partialResult = hal_result->partial_result;
973 convertToHidl(hal_result->result, &result.result);
974 if (hasInputBuf) {
975 result.inputBuffer.streamId =
976 static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
977 result.inputBuffer.buffer = nullptr;
978 result.inputBuffer.status = (BufferStatus) hal_result->input_buffer->status;
979 // skip acquire fence since it's no use to camera service
980 if (hal_result->input_buffer->release_fence != -1) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800981 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
982 handle->data[0] = hal_result->input_buffer->release_fence;
983 result.inputBuffer.releaseFence = handle;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800984 } else {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800985 result.inputBuffer.releaseFence = nullptr;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700986 }
987 } else {
988 result.inputBuffer.streamId = -1;
989 }
990
991 result.outputBuffers.resize(numOutputBufs);
992 for (size_t i = 0; i < numOutputBufs; i++) {
993 result.outputBuffers[i].streamId =
994 static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
995 result.outputBuffers[i].buffer = nullptr;
996 result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
997 // skip acquire fence since it's of no use to camera service
998 if (hal_result->output_buffers[i].release_fence != -1) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800999 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
1000 handle->data[0] = hal_result->output_buffers[i].release_fence;
1001 result.outputBuffers[i].releaseFence = handle;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001002 } else {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001003 result.outputBuffers[i].releaseFence = nullptr;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001004 }
1005 }
1006
1007 // Free inflight record/fences.
1008 // Do this before call back to camera service because camera service might jump to
1009 // configure_streams right after the processCaptureResult call so we need to finish
1010 // updating inflight queues first
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001011 if (numBufs > 0) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001012 Mutex::Autolock _l(d->mInflightLock);
1013 if (hasInputBuf) {
1014 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1015 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001016 d->mInflightBuffers.erase(key);
1017 }
1018
1019 for (size_t i = 0; i < numOutputBufs; i++) {
1020 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1021 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001022 d->mInflightBuffers.erase(key);
1023 }
1024
1025 if (d->mInflightBuffers.empty()) {
1026 ALOGV("%s: inflight buffer queue is now empty!", __FUNCTION__);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001027 }
1028 }
1029
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001030 d->mResultBatcher.processCaptureResult(result);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001031}
1032
1033void CameraDeviceSession::sNotify(
1034 const camera3_callback_ops *cb,
1035 const camera3_notify_msg *msg) {
1036 CameraDeviceSession *d =
1037 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
1038 NotifyMsg hidlMsg;
1039 convertToHidl(msg, &hidlMsg);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001040
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001041 if (hidlMsg.type == (MsgType) CAMERA3_MSG_ERROR &&
1042 hidlMsg.msg.error.errorStreamId != -1) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001043 if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
1044 ALOGE("%s: unknown stream ID %d reports an error!",
1045 __FUNCTION__, hidlMsg.msg.error.errorStreamId);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001046 return;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001047 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001048 }
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001049 d->mResultBatcher.notify(hidlMsg);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001050}
1051
1052} // namespace implementation
1053} // namespace V3_2
1054} // namespace device
1055} // namespace camera
1056} // namespace hardware
1057} // namespace android