summaryrefslogtreecommitdiffstats
path: root/services/camera/libcameraservice/device3
diff options
context:
space:
mode:
Diffstat (limited to 'services/camera/libcameraservice/device3')
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.cpp478
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.h94
-rw-r--r--services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp58
-rw-r--r--services/camera/libcameraservice/device3/Camera3IOStreamBase.h12
-rw-r--r--services/camera/libcameraservice/device3/Camera3InputStream.cpp34
-rw-r--r--services/camera/libcameraservice/device3/Camera3InputStream.h2
-rw-r--r--services/camera/libcameraservice/device3/Camera3OutputStream.cpp4
-rw-r--r--services/camera/libcameraservice/device3/Camera3Stream.cpp99
-rw-r--r--services/camera/libcameraservice/device3/Camera3Stream.h26
-rw-r--r--services/camera/libcameraservice/device3/Camera3ZslStream.cpp14
-rw-r--r--services/camera/libcameraservice/device3/Camera3ZslStream.h4
11 files changed, 616 insertions, 209 deletions
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 1d4768c..16d6f42 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -102,8 +102,10 @@ status_t Camera3Device::initialize(camera_module_t *module)
camera3_device_t *device;
+ ATRACE_BEGIN("camera3->open");
res = module->common.methods->open(&module->common, deviceName.string(),
reinterpret_cast<hw_device_t**>(&device));
+ ATRACE_END();
if (res != OK) {
SET_ERR_L("Could not open camera: %s (%d)", strerror(-res), res);
@@ -112,9 +114,9 @@ status_t Camera3Device::initialize(camera_module_t *module)
/** Cross-check device version */
- if (device->common.version != CAMERA_DEVICE_API_VERSION_3_0) {
+ if (device->common.version < CAMERA_DEVICE_API_VERSION_3_0) {
SET_ERR_L("Could not open camera: "
- "Camera device is not version %x, reports %x instead",
+ "Camera device should be at least %x, reports %x instead",
CAMERA_DEVICE_API_VERSION_3_0,
device->common.version);
device->common.close(&device->common);
@@ -128,7 +130,7 @@ status_t Camera3Device::initialize(camera_module_t *module)
if (info.device_version != device->common.version) {
SET_ERR_L("HAL reporting mismatched camera_info version (%x)"
" and device version (%x).",
- device->common.version, info.device_version);
+ info.device_version, device->common.version);
device->common.close(&device->common);
return BAD_VALUE;
}
@@ -146,24 +148,6 @@ status_t Camera3Device::initialize(camera_module_t *module)
return BAD_VALUE;
}
- /** Get vendor metadata tags */
-
- mVendorTagOps.get_camera_vendor_section_name = NULL;
-
- ATRACE_BEGIN("camera3->get_metadata_vendor_tag_ops");
- device->ops->get_metadata_vendor_tag_ops(device, &mVendorTagOps);
- ATRACE_END();
-
- if (mVendorTagOps.get_camera_vendor_section_name != NULL) {
- res = set_camera_metadata_vendor_tag_ops(&mVendorTagOps);
- if (res != OK) {
- SET_ERR_L("Unable to set tag ops: %s (%d)",
- strerror(-res), res);
- device->common.close(&device->common);
- return res;
- }
- }
-
/** Start up status tracker thread */
mStatusTracker = new StatusTracker(this);
res = mStatusTracker->run(String8::format("C3Dev-%d-Status", mId).string());
@@ -271,7 +255,9 @@ status_t Camera3Device::disconnect() {
mStatusTracker.clear();
if (mHal3Device != NULL) {
+ ATRACE_BEGIN("camera3->close");
mHal3Device->common.close(&mHal3Device->common);
+ ATRACE_END();
mHal3Device = NULL;
}
@@ -298,6 +284,53 @@ bool Camera3Device::tryLockSpinRightRound(Mutex& lock) {
return gotLock;
}
+ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const {
+ // TODO: replace below with availableStreamConfiguration for HAL3.2+.
+ camera_metadata_ro_entry availableJpegSizes =
+ mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_JPEG_SIZES);
+ if (availableJpegSizes.count == 0 || availableJpegSizes.count % 2 != 0) {
+ ALOGE("%s: Camera %d: Can't find find valid available jpeg sizes in static metadata!",
+ __FUNCTION__, mId);
+ return BAD_VALUE;
+ }
+
+ // Get max jpeg size (area-wise).
+ int32_t maxJpegWidth = 0, maxJpegHeight = 0;
+ bool foundMax = false;
+ for (size_t i = 0; i < availableJpegSizes.count; i += 2) {
+ if ((availableJpegSizes.data.i32[i] * availableJpegSizes.data.i32[i + 1])
+ > (maxJpegWidth * maxJpegHeight)) {
+ maxJpegWidth = availableJpegSizes.data.i32[i];
+ maxJpegHeight = availableJpegSizes.data.i32[i + 1];
+ foundMax = true;
+ }
+ }
+ if (!foundMax) {
+ return BAD_VALUE;
+ }
+
+ // Get max jpeg buffer size
+ ssize_t maxJpegBufferSize = 0;
+ camera_metadata_ro_entry jpegMaxSize = mDeviceInfo.find(ANDROID_JPEG_MAX_SIZE);
+ if (jpegMaxSize.count == 0) {
+ ALOGE("%s: Camera %d: Can't find maximum JPEG size in static metadata!", __FUNCTION__, mId);
+ return BAD_VALUE;
+ }
+ maxJpegBufferSize = jpegMaxSize.data.i32[0];
+
+ // Calculate final jpeg buffer size for the given resolution.
+ float scaleFactor = ((float) (width * height)) / (maxJpegWidth * maxJpegHeight);
+ ssize_t jpegBufferSize = scaleFactor * maxJpegBufferSize;
+ // Bound the buffer size to [MIN_JPEG_BUFFER_SIZE, maxJpegBufferSize].
+ if (jpegBufferSize > maxJpegBufferSize) {
+ jpegBufferSize = maxJpegBufferSize;
+ } else if (jpegBufferSize < kMinJpegBufferSize) {
+ jpegBufferSize = kMinJpegBufferSize;
+ }
+
+ return jpegBufferSize;
+}
+
status_t Camera3Device::dump(int fd, const Vector<String16> &args) {
ATRACE_CALL();
(void)args;
@@ -386,14 +419,7 @@ const CameraMetadata& Camera3Device::info() const {
return mDeviceInfo;
}
-status_t Camera3Device::capture(CameraMetadata &request) {
- ATRACE_CALL();
- status_t res;
- Mutex::Autolock il(mInterfaceLock);
- Mutex::Autolock l(mLock);
-
- // TODO: take ownership of the request
-
+status_t Camera3Device::checkStatusOkToCaptureLocked() {
switch (mStatus) {
case STATUS_ERROR:
CLOGE("Device has encountered a serious error");
@@ -402,7 +428,6 @@ status_t Camera3Device::capture(CameraMetadata &request) {
CLOGE("Device not initialized");
return INVALID_OPERATION;
case STATUS_UNCONFIGURED:
- // May be lazily configuring streams, will check during setup
case STATUS_CONFIGURED:
case STATUS_ACTIVE:
// OK
@@ -411,71 +436,119 @@ status_t Camera3Device::capture(CameraMetadata &request) {
SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
+ return OK;
+}
- sp<CaptureRequest> newRequest = setUpRequestLocked(request);
- if (newRequest == NULL) {
- CLOGE("Can't create capture request");
+status_t Camera3Device::convertMetadataListToRequestListLocked(
+ const List<const CameraMetadata> &metadataList, RequestList *requestList) {
+ if (requestList == NULL) {
+ CLOGE("requestList cannot be NULL.");
return BAD_VALUE;
}
- res = mRequestThread->queueRequest(newRequest);
- if (res == OK) {
- waitUntilStateThenRelock(/*active*/ true, kActiveTimeout);
- if (res != OK) {
- SET_ERR_L("Can't transition to active in %f seconds!",
- kActiveTimeout/1e9);
+ int32_t burstId = 0;
+ for (List<const CameraMetadata>::const_iterator it = metadataList.begin();
+ it != metadataList.end(); ++it) {
+ sp<CaptureRequest> newRequest = setUpRequestLocked(*it);
+ if (newRequest == 0) {
+ CLOGE("Can't create capture request");
+ return BAD_VALUE;
}
- ALOGV("Camera %d: Capture request enqueued", mId);
+
+ // Setup burst Id and request Id
+ newRequest->mResultExtras.burstId = burstId++;
+ if (it->exists(ANDROID_REQUEST_ID)) {
+ if (it->find(ANDROID_REQUEST_ID).count == 0) {
+ CLOGE("RequestID entry exists; but must not be empty in metadata");
+ return BAD_VALUE;
+ }
+ newRequest->mResultExtras.requestId = it->find(ANDROID_REQUEST_ID).data.i32[0];
+ } else {
+ CLOGE("RequestID does not exist in metadata");
+ return BAD_VALUE;
+ }
+
+ requestList->push_back(newRequest);
+
+ ALOGV("%s: requestId = %" PRId32, __FUNCTION__, newRequest->mResultExtras.requestId);
}
- return res;
+ return OK;
}
+status_t Camera3Device::capture(CameraMetadata &request, int64_t* /*lastFrameNumber*/) {
+ ATRACE_CALL();
+
+ List<const CameraMetadata> requests;
+ requests.push_back(request);
+ return captureList(requests, /*lastFrameNumber*/NULL);
+}
-status_t Camera3Device::setStreamingRequest(const CameraMetadata &request) {
+status_t Camera3Device::submitRequestsHelper(
+ const List<const CameraMetadata> &requests, bool repeating,
+ /*out*/
+ int64_t *lastFrameNumber) {
ATRACE_CALL();
- status_t res;
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
- switch (mStatus) {
- case STATUS_ERROR:
- CLOGE("Device has encountered a serious error");
- return INVALID_OPERATION;
- case STATUS_UNINITIALIZED:
- CLOGE("Device not initialized");
- return INVALID_OPERATION;
- case STATUS_UNCONFIGURED:
- // May be lazily configuring streams, will check during setup
- case STATUS_CONFIGURED:
- case STATUS_ACTIVE:
- // OK
- break;
- default:
- SET_ERR_L("Unexpected status: %d", mStatus);
- return INVALID_OPERATION;
+ status_t res = checkStatusOkToCaptureLocked();
+ if (res != OK) {
+ // error logged by previous call
+ return res;
}
- sp<CaptureRequest> newRepeatingRequest = setUpRequestLocked(request);
- if (newRepeatingRequest == NULL) {
- CLOGE("Can't create repeating request");
- return BAD_VALUE;
+ RequestList requestList;
+
+ res = convertMetadataListToRequestListLocked(requests, /*out*/&requestList);
+ if (res != OK) {
+ // error logged by previous call
+ return res;
}
- RequestList newRepeatingRequests;
- newRepeatingRequests.push_back(newRepeatingRequest);
+ if (repeating) {
+ res = mRequestThread->setRepeatingRequests(requestList, lastFrameNumber);
+ } else {
+ res = mRequestThread->queueRequestList(requestList, lastFrameNumber);
+ }
- res = mRequestThread->setRepeatingRequests(newRepeatingRequests);
if (res == OK) {
- waitUntilStateThenRelock(/*active*/ true, kActiveTimeout);
+ waitUntilStateThenRelock(/*active*/true, kActiveTimeout);
if (res != OK) {
SET_ERR_L("Can't transition to active in %f seconds!",
kActiveTimeout/1e9);
}
- ALOGV("Camera %d: Repeating request set", mId);
+ ALOGV("Camera %d: Capture request %" PRId32 " enqueued", mId,
+ (*(requestList.begin()))->mResultExtras.requestId);
+ } else {
+ CLOGE("Cannot queue request. Impossible.");
+ return BAD_VALUE;
}
+
return res;
}
+status_t Camera3Device::captureList(const List<const CameraMetadata> &requests,
+ int64_t *lastFrameNumber) {
+ ATRACE_CALL();
+
+ return submitRequestsHelper(requests, /*repeating*/false, lastFrameNumber);
+}
+
+status_t Camera3Device::setStreamingRequest(const CameraMetadata &request,
+ int64_t* /*lastFrameNumber*/) {
+ ATRACE_CALL();
+
+ List<const CameraMetadata> requests;
+ requests.push_back(request);
+ return setStreamingRequestList(requests, /*lastFrameNumber*/NULL);
+}
+
+status_t Camera3Device::setStreamingRequestList(const List<const CameraMetadata> &requests,
+ int64_t *lastFrameNumber) {
+ ATRACE_CALL();
+
+ return submitRequestsHelper(requests, /*repeating*/true, lastFrameNumber);
+}
sp<Camera3Device::CaptureRequest> Camera3Device::setUpRequestLocked(
const CameraMetadata &request) {
@@ -497,7 +570,7 @@ sp<Camera3Device::CaptureRequest> Camera3Device::setUpRequestLocked(
return newRequest;
}
-status_t Camera3Device::clearStreamingRequest() {
+status_t Camera3Device::clearStreamingRequest(int64_t *lastFrameNumber) {
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
@@ -519,7 +592,8 @@ status_t Camera3Device::clearStreamingRequest() {
return INVALID_OPERATION;
}
ALOGV("Camera %d: Clearing repeating request", mId);
- return mRequestThread->clearRepeatingRequests();
+
+ return mRequestThread->clearRepeatingRequests(lastFrameNumber);
}
status_t Camera3Device::waitUntilRequestReceived(int32_t requestId, nsecs_t timeout) {
@@ -714,8 +788,17 @@ status_t Camera3Device::createStream(sp<ANativeWindow> consumer,
sp<Camera3OutputStream> newStream;
if (format == HAL_PIXEL_FORMAT_BLOB) {
+ ssize_t jpegBufferSize = getJpegBufferSize(width, height);
+ if (jpegBufferSize > 0) {
+ ALOGV("%s: Overwrite Jpeg output buffer size from %zu to %zu",
+ __FUNCTION__, size, jpegBufferSize);
+ } else {
+ SET_ERR_L("Invalid jpeg buffer size %zd", jpegBufferSize);
+ return BAD_VALUE;
+ }
+
newStream = new Camera3OutputStream(mNextStreamId, consumer,
- width, height, size, format);
+ width, height, jpegBufferSize, format);
} else {
newStream = new Camera3OutputStream(mNextStreamId, consumer,
width, height, format);
@@ -840,16 +923,20 @@ status_t Camera3Device::deleteStream(int id) {
}
sp<Camera3StreamInterface> deletedStream;
+ ssize_t outputStreamIdx = mOutputStreams.indexOfKey(id);
if (mInputStream != NULL && id == mInputStream->getId()) {
deletedStream = mInputStream;
mInputStream.clear();
} else {
- ssize_t idx = mOutputStreams.indexOfKey(id);
- if (idx == NAME_NOT_FOUND) {
+ if (outputStreamIdx == NAME_NOT_FOUND) {
CLOGE("Stream %d does not exist", id);
return BAD_VALUE;
}
- deletedStream = mOutputStreams.editValueAt(idx);
+ }
+
+ // Delete output stream or the output part of a bi-directional stream.
+ if (outputStreamIdx != NAME_NOT_FOUND) {
+ deletedStream = mOutputStreams.editValueAt(outputStreamIdx);
mOutputStreams.removeItem(id);
}
@@ -918,6 +1005,10 @@ status_t Camera3Device::waitUntilDrained() {
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
+ return waitUntilDrainedLocked();
+}
+
+status_t Camera3Device::waitUntilDrainedLocked() {
switch (mStatus) {
case STATUS_UNINITIALIZED:
case STATUS_UNCONFIGURED:
@@ -1030,7 +1121,7 @@ status_t Camera3Device::waitForNextFrame(nsecs_t timeout) {
return OK;
}
-status_t Camera3Device::getNextFrame(CameraMetadata *frame) {
+status_t Camera3Device::getNextResult(CaptureResult *frame) {
ATRACE_CALL();
Mutex::Autolock l(mOutputLock);
@@ -1038,8 +1129,14 @@ status_t Camera3Device::getNextFrame(CameraMetadata *frame) {
return NOT_ENOUGH_DATA;
}
- CameraMetadata &result = *(mResultQueue.begin());
- frame->acquire(result);
+ if (frame == NULL) {
+ ALOGE("%s: argument cannot be NULL", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ CaptureResult &result = *(mResultQueue.begin());
+ frame->mResultExtras = result.mResultExtras;
+ frame->mMetadata.acquire(result.mMetadata);
mResultQueue.erase(mResultQueue.begin());
return OK;
@@ -1117,14 +1214,25 @@ status_t Camera3Device::pushReprocessBuffer(int reprocessStreamId,
return INVALID_OPERATION;
}
-status_t Camera3Device::flush() {
+status_t Camera3Device::flush(int64_t *frameNumber) {
ATRACE_CALL();
ALOGV("%s: Camera %d: Flushing all requests", __FUNCTION__, mId);
Mutex::Autolock il(mInterfaceLock);
- Mutex::Autolock l(mLock);
- mRequestThread->clear();
- return mHal3Device->ops->flush(mHal3Device);
+ {
+ Mutex::Autolock l(mLock);
+ mRequestThread->clear(/*out*/frameNumber);
+ }
+
+ status_t res;
+ if (mHal3Device->common.version >= CAMERA_DEVICE_API_VERSION_3_1) {
+ res = mHal3Device->ops->flush(mHal3Device);
+ } else {
+ Mutex::Autolock l(mLock);
+ res = waitUntilDrainedLocked();
+ }
+
+ return res;
}
/**
@@ -1392,13 +1500,13 @@ void Camera3Device::setErrorStateLockedV(const char *fmt, va_list args) {
* In-flight request management
*/
-status_t Camera3Device::registerInFlight(int32_t frameNumber,
- int32_t requestId, int32_t numBuffers) {
+status_t Camera3Device::registerInFlight(uint32_t frameNumber,
+ int32_t numBuffers, CaptureResultExtras resultExtras) {
ATRACE_CALL();
Mutex::Autolock l(mInFlightLock);
ssize_t res;
- res = mInFlightMap.add(frameNumber, InFlightRequest(requestId, numBuffers));
+ res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers, resultExtras));
if (res < 0) return res;
return OK;
@@ -1410,8 +1518,8 @@ status_t Camera3Device::registerInFlight(int32_t frameNumber,
* to the output frame queue
*/
bool Camera3Device::processPartial3AQuirk(
- int32_t frameNumber, int32_t requestId,
- const CameraMetadata& partial) {
+ uint32_t frameNumber,
+ const CameraMetadata& partial, const CaptureResultExtras& resultExtras) {
// Check if all 3A states are present
// The full list of fields is
@@ -1460,7 +1568,7 @@ bool Camera3Device::processPartial3AQuirk(
ALOGVV("%s: Camera %d: Frame %d, Request ID %d: AF mode %d, AWB mode %d, "
"AF state %d, AE state %d, AWB state %d, "
"AF trigger %d, AE precapture trigger %d",
- __FUNCTION__, mId, frameNumber, requestId,
+ __FUNCTION__, mId, frameNumber, resultExtras.requestId,
afMode, awbMode,
afState, aeState, awbState,
afTriggerId, aeTriggerId);
@@ -1475,58 +1583,63 @@ bool Camera3Device::processPartial3AQuirk(
Mutex::Autolock l(mOutputLock);
- CameraMetadata& min3AResult =
- *mResultQueue.insert(
- mResultQueue.end(),
- CameraMetadata(kMinimal3AResultEntries, /*dataCapacity*/ 0));
-
- if (!insert3AResult(min3AResult, ANDROID_REQUEST_FRAME_COUNT,
- &frameNumber, frameNumber)) {
+ CaptureResult captureResult;
+ captureResult.mResultExtras = resultExtras;
+ captureResult.mMetadata = CameraMetadata(kMinimal3AResultEntries, /*dataCapacity*/ 0);
+ // TODO: change this to sp<CaptureResult>. This will need other changes, including,
+ // but not limited to CameraDeviceBase::getNextResult
+ CaptureResult& min3AResult =
+ *mResultQueue.insert(mResultQueue.end(), captureResult);
+
+ if (!insert3AResult(min3AResult.mMetadata, ANDROID_REQUEST_FRAME_COUNT,
+ // TODO: This is problematic casting. Need to fix CameraMetadata.
+ reinterpret_cast<int32_t*>(&frameNumber), frameNumber)) {
return false;
}
- if (!insert3AResult(min3AResult, ANDROID_REQUEST_ID,
+ int32_t requestId = resultExtras.requestId;
+ if (!insert3AResult(min3AResult.mMetadata, ANDROID_REQUEST_ID,
&requestId, frameNumber)) {
return false;
}
static const uint8_t partialResult = ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL;
- if (!insert3AResult(min3AResult, ANDROID_QUIRKS_PARTIAL_RESULT,
+ if (!insert3AResult(min3AResult.mMetadata, ANDROID_QUIRKS_PARTIAL_RESULT,
&partialResult, frameNumber)) {
return false;
}
- if (!insert3AResult(min3AResult, ANDROID_CONTROL_AF_MODE,
+ if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AF_MODE,
&afMode, frameNumber)) {
return false;
}
- if (!insert3AResult(min3AResult, ANDROID_CONTROL_AWB_MODE,
+ if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AWB_MODE,
&awbMode, frameNumber)) {
return false;
}
- if (!insert3AResult(min3AResult, ANDROID_CONTROL_AE_STATE,
+ if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AE_STATE,
&aeState, frameNumber)) {
return false;
}
- if (!insert3AResult(min3AResult, ANDROID_CONTROL_AF_STATE,
+ if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AF_STATE,
&afState, frameNumber)) {
return false;
}
- if (!insert3AResult(min3AResult, ANDROID_CONTROL_AWB_STATE,
+ if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AWB_STATE,
&awbState, frameNumber)) {
return false;
}
- if (!insert3AResult(min3AResult, ANDROID_CONTROL_AF_TRIGGER_ID,
+ if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AF_TRIGGER_ID,
&afTriggerId, frameNumber)) {
return false;
}
- if (!insert3AResult(min3AResult, ANDROID_CONTROL_AE_PRECAPTURE_ID,
+ if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AE_PRECAPTURE_ID,
&aeTriggerId, frameNumber)) {
return false;
}
@@ -1538,7 +1651,7 @@ bool Camera3Device::processPartial3AQuirk(
template<typename T>
bool Camera3Device::get3AResult(const CameraMetadata& result, int32_t tag,
- T* value, int32_t frameNumber) {
+ T* value, uint32_t frameNumber) {
(void) frameNumber;
camera_metadata_ro_entry_t entry;
@@ -1563,7 +1676,7 @@ bool Camera3Device::get3AResult(const CameraMetadata& result, int32_t tag,
template<typename T>
bool Camera3Device::insert3AResult(CameraMetadata& result, int32_t tag,
- const T* value, int32_t frameNumber) {
+ const T* value, uint32_t frameNumber) {
if (result.update(tag, value, 1) != NO_ERROR) {
mResultQueue.erase(--mResultQueue.end(), mResultQueue.end());
SET_ERR("Frame %d: Failed to set %s in partial metadata",
@@ -1590,11 +1703,12 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
}
bool partialResultQuirk = false;
CameraMetadata collectedQuirkResult;
+ CaptureResultExtras resultExtras;
- // Get capture timestamp from list of in-flight requests, where it was added
- // by the shutter notification for this frame. Then update the in-flight
- // status and remove the in-flight entry if all result data has been
- // received.
+ // Get capture timestamp and resultExtras from list of in-flight requests,
+ // where it was added by the shutter notification for this frame.
+ // Then update the in-flight status and remove the in-flight entry if
+ // all result data has been received.
nsecs_t timestamp = 0;
{
Mutex::Autolock l(mInFlightLock);
@@ -1605,6 +1719,10 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
return;
}
InFlightRequest &request = mInFlightMap.editValueAt(idx);
+ ALOGVV("%s: got InFlightRequest requestId = %" PRId32 ", frameNumber = %" PRId64
+ ", burstId = %" PRId32,
+ __FUNCTION__, request.resultExtras.requestId, request.resultExtras.frameNumber,
+ request.resultExtras.burstId);
// Check if this result carries only partial metadata
if (mUsePartialResultQuirk && result->result != NULL) {
@@ -1626,13 +1744,15 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
if (!request.partialResultQuirk.haveSent3A) {
request.partialResultQuirk.haveSent3A =
processPartial3AQuirk(frameNumber,
- request.requestId,
- request.partialResultQuirk.collectedResult);
+ request.partialResultQuirk.collectedResult,
+ request.resultExtras);
}
}
}
timestamp = request.captureTimestamp;
+ resultExtras = request.resultExtras;
+
/**
* One of the following must happen before it's legal to call process_capture_result,
* unless partial metadata is being provided:
@@ -1668,8 +1788,10 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
return;
}
- // Check if everything has arrived for this result (buffers and metadata)
- if (request.haveResultMetadata && request.numBuffersLeft == 0) {
+ // Check if everything has arrived for this result (buffers and metadata), remove it from
+ // InFlightMap if both arrived or HAL reports error for this request (i.e. during flush).
+ if ((request.requestStatus != OK) ||
+ (request.haveResultMetadata && request.numBuffersLeft == 0)) {
ATRACE_ASYNC_END("frame capture", frameNumber);
mInFlightMap.removeItemsAt(idx, 1);
}
@@ -1689,19 +1811,21 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
gotResult = true;
- if (frameNumber != mNextResultFrameNumber) {
+ // TODO: need to track errors for tighter bounds on expected frame number
+ if (frameNumber < mNextResultFrameNumber) {
SET_ERR("Out-of-order capture result metadata submitted! "
"(got frame number %d, expecting %d)",
frameNumber, mNextResultFrameNumber);
return;
}
- mNextResultFrameNumber++;
+ mNextResultFrameNumber = frameNumber + 1;
- CameraMetadata captureResult;
- captureResult = result->result;
+ CaptureResult captureResult;
+ captureResult.mResultExtras = resultExtras;
+ captureResult.mMetadata = result->result;
- if (captureResult.update(ANDROID_REQUEST_FRAME_COUNT,
- (int32_t*)&frameNumber, 1) != OK) {
+ if (captureResult.mMetadata.update(ANDROID_REQUEST_FRAME_COUNT,
+ (int32_t*)&frameNumber, 1) != OK) {
SET_ERR("Failed to set frame# in metadata (%d)",
frameNumber);
gotResult = false;
@@ -1712,15 +1836,15 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
// Append any previous partials to form a complete result
if (mUsePartialResultQuirk && !collectedQuirkResult.isEmpty()) {
- captureResult.append(collectedQuirkResult);
+ captureResult.mMetadata.append(collectedQuirkResult);
}
- captureResult.sort();
+ captureResult.mMetadata.sort();
// Check that there's a timestamp in the result metadata
camera_metadata_entry entry =
- captureResult.find(ANDROID_SENSOR_TIMESTAMP);
+ captureResult.mMetadata.find(ANDROID_SENSOR_TIMESTAMP);
if (entry.count == 0) {
SET_ERR("No timestamp provided by HAL for frame %d!",
frameNumber);
@@ -1734,9 +1858,13 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
if (gotResult) {
// Valid result, insert into queue
- CameraMetadata& queuedResult =
- *mResultQueue.insert(mResultQueue.end(), CameraMetadata());
- queuedResult.swap(captureResult);
+ List<CaptureResult>::iterator queuedResult =
+ mResultQueue.insert(mResultQueue.end(), CaptureResult(captureResult));
+ ALOGVV("%s: result requestId = %" PRId32 ", frameNumber = %" PRId64
+ ", burstId = %" PRId32, __FUNCTION__,
+ queuedResult->mResultExtras.requestId,
+ queuedResult->mResultExtras.frameNumber,
+ queuedResult->mResultExtras.burstId);
}
} // scope for mOutputLock
@@ -1762,8 +1890,6 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
}
-
-
void Camera3Device::notify(const camera3_notify_msg *msg) {
ATRACE_CALL();
NotificationListener *listener;
@@ -1790,18 +1916,29 @@ void Camera3Device::notify(const camera3_notify_msg *msg) {
mId, __FUNCTION__, msg->message.error.frame_number,
streamId, msg->message.error.error_code);
+ CaptureResultExtras resultExtras;
// Set request error status for the request in the in-flight tracking
{
Mutex::Autolock l(mInFlightLock);
ssize_t idx = mInFlightMap.indexOfKey(msg->message.error.frame_number);
if (idx >= 0) {
- mInFlightMap.editValueAt(idx).requestStatus = msg->message.error.error_code;
+ InFlightRequest &r = mInFlightMap.editValueAt(idx);
+ r.requestStatus = msg->message.error.error_code;
+ resultExtras = r.resultExtras;
+ } else {
+ resultExtras.frameNumber = msg->message.error.frame_number;
+ ALOGE("Camera %d: %s: cannot find in-flight request on frame %" PRId64
+ " error", mId, __FUNCTION__, resultExtras.frameNumber);
}
}
if (listener != NULL) {
- listener->notifyError(msg->message.error.error_code,
- msg->message.error.frame_number, streamId);
+ if (msg->message.error.error_code == CAMERA3_MSG_ERROR_DEVICE) {
+ listener->notifyError(ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
+ resultExtras);
+ }
+ } else {
+ ALOGE("Camera %d: %s: no listener available", mId, __FUNCTION__);
}
break;
}
@@ -1812,16 +1949,17 @@ void Camera3Device::notify(const camera3_notify_msg *msg) {
// Verify ordering of shutter notifications
{
Mutex::Autolock l(mOutputLock);
- if (frameNumber != mNextShutterFrameNumber) {
+ // TODO: need to track errors for tighter bounds on expected frame number.
+ if (frameNumber < mNextShutterFrameNumber) {
SET_ERR("Shutter notification out-of-order. Expected "
"notification for frame %d, got frame %d",
mNextShutterFrameNumber, frameNumber);
break;
}
- mNextShutterFrameNumber++;
+ mNextShutterFrameNumber = frameNumber + 1;
}
- int32_t requestId = -1;
+ CaptureResultExtras resultExtras;
// Set timestamp for the request in the in-flight tracking
// and get the request ID to send upstream
@@ -1831,7 +1969,7 @@ void Camera3Device::notify(const camera3_notify_msg *msg) {
if (idx >= 0) {
InFlightRequest &r = mInFlightMap.editValueAt(idx);
r.captureTimestamp = timestamp;
- requestId = r.requestId;
+ resultExtras = r.resultExtras;
}
}
if (idx < 0) {
@@ -1840,10 +1978,10 @@ void Camera3Device::notify(const camera3_notify_msg *msg) {
break;
}
ALOGVV("Camera %d: %s: Shutter fired for frame %d (id %d) at %" PRId64,
- mId, __FUNCTION__, frameNumber, requestId, timestamp);
+ mId, __FUNCTION__, frameNumber, resultExtras.requestId, timestamp);
// Call listener, if any
if (listener != NULL) {
- listener->notifyShutter(requestId, timestamp);
+ listener->notifyShutter(resultExtras, timestamp);
}
break;
}
@@ -1865,6 +2003,7 @@ CameraMetadata Camera3Device::getLatestRequestLocked() {
return retVal;
}
+
/**
* RequestThread inner class methods
*/
@@ -1881,7 +2020,8 @@ Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent,
mDoPause(false),
mPaused(true),
mFrameNumber(0),
- mLatestRequestId(NAME_NOT_FOUND) {
+ mLatestRequestId(NAME_NOT_FOUND),
+ mRepeatingLastFrameNumber(NO_IN_FLIGHT_REPEATING_FRAMES) {
mStatusId = statusTracker->addComponent();
}
@@ -1890,10 +2030,22 @@ void Camera3Device::RequestThread::configurationComplete() {
mReconfigured = true;
}
-status_t Camera3Device::RequestThread::queueRequest(
- sp<CaptureRequest> request) {
+status_t Camera3Device::RequestThread::queueRequestList(
+ List<sp<CaptureRequest> > &requests,
+ /*out*/
+ int64_t *lastFrameNumber) {
Mutex::Autolock l(mRequestLock);
- mRequestQueue.push_back(request);
+ for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end();
+ ++it) {
+ mRequestQueue.push_back(*it);
+ }
+
+ if (lastFrameNumber != NULL) {
+ *lastFrameNumber = mFrameNumber + mRequestQueue.size() - 1;
+ ALOGV("%s: requestId %d, mFrameNumber %" PRId32 ", lastFrameNumber %" PRId64 ".",
+ __FUNCTION__, (*(requests.begin()))->mResultExtras.requestId, mFrameNumber,
+ *lastFrameNumber);
+ }
unpauseForNewRequests();
@@ -1957,28 +2109,43 @@ status_t Camera3Device::RequestThread::queueTriggerLocked(
}
status_t Camera3Device::RequestThread::setRepeatingRequests(
- const RequestList &requests) {
+ const RequestList &requests,
+ /*out*/
+ int64_t *lastFrameNumber) {
Mutex::Autolock l(mRequestLock);
+ if (lastFrameNumber != NULL) {
+ *lastFrameNumber = mRepeatingLastFrameNumber;
+ }
mRepeatingRequests.clear();
mRepeatingRequests.insert(mRepeatingRequests.begin(),
requests.begin(), requests.end());
unpauseForNewRequests();
+ mRepeatingLastFrameNumber = NO_IN_FLIGHT_REPEATING_FRAMES;
return OK;
}
-status_t Camera3Device::RequestThread::clearRepeatingRequests() {
+status_t Camera3Device::RequestThread::clearRepeatingRequests(/*out*/int64_t *lastFrameNumber) {
Mutex::Autolock l(mRequestLock);
mRepeatingRequests.clear();
+ if (lastFrameNumber != NULL) {
+ *lastFrameNumber = mRepeatingLastFrameNumber;
+ }
+ mRepeatingLastFrameNumber = NO_IN_FLIGHT_REPEATING_FRAMES;
return OK;
}
-status_t Camera3Device::RequestThread::clear() {
+status_t Camera3Device::RequestThread::clear(/*out*/int64_t *lastFrameNumber) {
Mutex::Autolock l(mRequestLock);
+ ALOGV("RequestThread::%s:", __FUNCTION__);
mRepeatingRequests.clear();
mRequestQueue.clear();
mTriggerMap.clear();
+ if (lastFrameNumber != NULL) {
+ *lastFrameNumber = mRepeatingLastFrameNumber;
+ }
+ mRepeatingLastFrameNumber = NO_IN_FLIGHT_REPEATING_FRAMES;
return OK;
}
@@ -2030,6 +2197,7 @@ bool Camera3Device::RequestThread::threadLoop() {
// Create request to HAL
camera3_capture_request_t request = camera3_capture_request_t();
+ request.frame_number = nextRequest->mResultExtras.frameNumber;
Vector<camera3_stream_buffer_t> outputBuffers;
// Get the request ID, if any
@@ -2050,7 +2218,7 @@ bool Camera3Device::RequestThread::threadLoop() {
if (res < 0) {
SET_ERR("RequestThread: Unable to insert triggers "
"(capture request %d, HAL device: %s (%d)",
- (mFrameNumber+1), strerror(-res), res);
+ request.frame_number, strerror(-res), res);
cleanUpFailedRequest(request, nextRequest, outputBuffers);
return false;
}
@@ -2068,7 +2236,7 @@ bool Camera3Device::RequestThread::threadLoop() {
if (res != OK) {
SET_ERR("RequestThread: Unable to insert dummy trigger IDs "
"(capture request %d, HAL device: %s (%d)",
- (mFrameNumber+1), strerror(-res), res);
+ request.frame_number, strerror(-res), res);
cleanUpFailedRequest(request, nextRequest, outputBuffers);
return false;
}
@@ -2092,7 +2260,7 @@ bool Camera3Device::RequestThread::threadLoop() {
if (e.count > 0) {
ALOGV("%s: Request (frame num %d) had AF trigger 0x%x",
__FUNCTION__,
- mFrameNumber+1,
+ request.frame_number,
e.data.u8[0]);
}
}
@@ -2134,8 +2302,6 @@ bool Camera3Device::RequestThread::threadLoop() {
request.num_output_buffers++;
}
- request.frame_number = mFrameNumber++;
-
// Log request in the in-flight queue
sp<Camera3Device> parent = mParent.promote();
if (parent == NULL) {
@@ -2144,8 +2310,13 @@ bool Camera3Device::RequestThread::threadLoop() {
return false;
}
- res = parent->registerInFlight(request.frame_number, requestId,
- request.num_output_buffers);
+ res = parent->registerInFlight(request.frame_number,
+ request.num_output_buffers, nextRequest->mResultExtras);
+ ALOGVV("%s: registered in flight requestId = %" PRId32 ", frameNumber = %" PRId64
+ ", burstId = %" PRId32 ".",
+ __FUNCTION__,
+ nextRequest->mResultExtras.requestId, nextRequest->mResultExtras.frameNumber,
+ nextRequest->mResultExtras.burstId);
if (res != OK) {
SET_ERR("RequestThread: Unable to register new in-flight request:"
" %s (%d)", strerror(-res), res);
@@ -2222,6 +2393,7 @@ CameraMetadata Camera3Device::RequestThread::getLatestRequest() const {
return mLatestRequest;
}
+
void Camera3Device::RequestThread::cleanUpFailedRequest(
camera3_capture_request_t &request,
sp<CaptureRequest> &nextRequest,
@@ -2263,6 +2435,9 @@ sp<Camera3Device::CaptureRequest>
++firstRequest,
requests.end());
// No need to wait any longer
+
+ mRepeatingLastFrameNumber = mFrameNumber + requests.size() - 1;
+
break;
}
@@ -2314,6 +2489,9 @@ sp<Camera3Device::CaptureRequest>
mReconfigured = false;
}
+ if (nextRequest != NULL) {
+ nextRequest->mResultExtras.frameNumber = mFrameNumber++;
+ }
return nextRequest;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 468f641..00ae771 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -24,6 +24,8 @@
#include <utils/Thread.h>
#include <utils/KeyedVector.h>
#include <hardware/camera3.h>
+#include <camera/CaptureResult.h>
+#include <camera/camera2/ICameraDeviceUser.h>
#include "common/CameraDeviceBase.h"
#include "device3/StatusTracker.h"
@@ -54,7 +56,7 @@ class Camera3StreamInterface;
}
/**
- * CameraDevice for HAL devices with version CAMERA_DEVICE_API_VERSION_3_0
+ * CameraDevice for HAL devices with version CAMERA_DEVICE_API_VERSION_3_0 or higher.
*/
class Camera3Device :
public CameraDeviceBase,
@@ -78,15 +80,21 @@ class Camera3Device :
// Capture and setStreamingRequest will configure streams if currently in
// idle state
- virtual status_t capture(CameraMetadata &request);
- virtual status_t setStreamingRequest(const CameraMetadata &request);
- virtual status_t clearStreamingRequest();
+ virtual status_t capture(CameraMetadata &request, int64_t *lastFrameNumber = NULL);
+ virtual status_t captureList(const List<const CameraMetadata> &requests,
+ int64_t *lastFrameNumber = NULL);
+ virtual status_t setStreamingRequest(const CameraMetadata &request,
+ int64_t *lastFrameNumber = NULL);
+ virtual status_t setStreamingRequestList(const List<const CameraMetadata> &requests,
+ int64_t *lastFrameNumber = NULL);
+ virtual status_t clearStreamingRequest(int64_t *lastFrameNumber = NULL);
virtual status_t waitUntilRequestReceived(int32_t requestId, nsecs_t timeout);
// Actual stream creation/deletion is delayed until first request is submitted
// If adding streams while actively capturing, will pause device before adding
- // stream, reconfiguring device, and unpausing.
+ // stream, reconfiguring device, and unpausing. Note that, for JPEG stream, the
+ // buffer size may be overwritten by an more accurate value calculated by Camera3Device.
virtual status_t createStream(sp<ANativeWindow> consumer,
uint32_t width, uint32_t height, int format, size_t size,
int *id);
@@ -116,7 +124,7 @@ class Camera3Device :
virtual status_t setNotifyCallback(NotificationListener *listener);
virtual bool willNotify3A();
virtual status_t waitForNextFrame(nsecs_t timeout);
- virtual status_t getNextFrame(CameraMetadata *frame);
+ virtual status_t getNextResult(CaptureResult *frame);
virtual status_t triggerAutofocus(uint32_t id);
virtual status_t triggerCancelAutofocus(uint32_t id);
@@ -125,7 +133,7 @@ class Camera3Device :
virtual status_t pushReprocessBuffer(int reprocessStreamId,
buffer_handle_t *buffer, wp<BufferReleasedListener> listener);
- virtual status_t flush();
+ virtual status_t flush(int64_t *lastFrameNumber = NULL);
// Methods called by subclasses
void notifyStatus(bool idle); // updates from StatusTracker
@@ -137,6 +145,8 @@ class Camera3Device :
static const nsecs_t kShutdownTimeout = 5000000000; // 5 sec
static const nsecs_t kActiveTimeout = 500000000; // 500 ms
struct RequestTrigger;
+ // minimal jpeg buffer size: 256KB + blob header
+ static const ssize_t kMinJpegBufferSize = 256 * 1024 + sizeof(camera3_jpeg_blob);
// A lock to enforce serialization on the input/configure side
// of the public interface.
@@ -157,7 +167,6 @@ class Camera3Device :
camera3_device_t *mHal3Device;
CameraMetadata mDeviceInfo;
- vendor_tag_query_ops_t mVendorTagOps;
enum Status {
STATUS_ERROR,
@@ -199,9 +208,20 @@ class Camera3Device :
sp<camera3::Camera3Stream> mInputStream;
Vector<sp<camera3::Camera3OutputStreamInterface> >
mOutputStreams;
+ CaptureResultExtras mResultExtras;
};
typedef List<sp<CaptureRequest> > RequestList;
+ status_t checkStatusOkToCaptureLocked();
+
+ status_t convertMetadataListToRequestListLocked(
+ const List<const CameraMetadata> &metadataList,
+ /*out*/
+ RequestList *requestList);
+
+ status_t submitRequestsHelper(const List<const CameraMetadata> &requests, bool repeating,
+ int64_t *lastFrameNumber = NULL);
+
/**
* Get the last request submitted to the hal by the request thread.
*
@@ -237,6 +257,13 @@ class Camera3Device :
status_t waitUntilStateThenRelock(bool active, nsecs_t timeout);
/**
+ * Implementation of waitUntilDrained. On success, will transition to IDLE state.
+ *
+ * Need to be called with mLock and mInterfaceLock held.
+ */
+ status_t waitUntilDrainedLocked();
+
+ /**
* Do common work for setting up a streaming or single capture request.
* On success, will transition to ACTIVE if in IDLE.
*/
@@ -270,6 +297,12 @@ class Camera3Device :
*/
bool tryLockSpinRightRound(Mutex& lock);
+ /**
+ * Get Jpeg buffer size for a given jpeg resolution.
+ * Negative values are error codes.
+ */
+ ssize_t getJpegBufferSize(uint32_t width, uint32_t height) const;
+
struct RequestTrigger {
// Metadata tag number, e.g. android.control.aePrecaptureTrigger
uint32_t metadataTag;
@@ -308,15 +341,21 @@ class Camera3Device :
* on either. Use waitUntilPaused to wait until request queue
* has emptied out.
*/
- status_t setRepeatingRequests(const RequestList& requests);
- status_t clearRepeatingRequests();
+ status_t setRepeatingRequests(const RequestList& requests,
+ /*out*/
+ int64_t *lastFrameNumber = NULL);
+ status_t clearRepeatingRequests(/*out*/
+ int64_t *lastFrameNumber = NULL);
- status_t queueRequest(sp<CaptureRequest> request);
+ status_t queueRequestList(List<sp<CaptureRequest> > &requests,
+ /*out*/
+ int64_t *lastFrameNumber = NULL);
/**
* Remove all queued and repeating requests, and pending triggers
*/
- status_t clear();
+ status_t clear(/*out*/
+ int64_t *lastFrameNumber = NULL);
/**
* Queue a trigger to be dispatched with the next outgoing
@@ -429,6 +468,8 @@ class Camera3Device :
TriggerMap mTriggerMap;
TriggerMap mTriggerRemovedMap;
TriggerMap mTriggerReplacedMap;
+
+ int64_t mRepeatingLastFrameNumber;
};
sp<RequestThread> mRequestThread;
@@ -437,8 +478,6 @@ class Camera3Device :
*/
struct InFlightRequest {
- // android.request.id for the request
- int requestId;
// Set by notify() SHUTTER call.
nsecs_t captureTimestamp;
int requestStatus;
@@ -447,6 +486,7 @@ class Camera3Device :
// Decremented by calls to process_capture_result with valid output
// buffers
int numBuffersLeft;
+ CaptureResultExtras resultExtras;
// Fields used by the partial result quirk only
struct PartialResultQuirkInFlight {
@@ -462,20 +502,26 @@ class Camera3Device :
// Default constructor needed by KeyedVector
InFlightRequest() :
- requestId(0),
captureTimestamp(0),
requestStatus(OK),
haveResultMetadata(false),
numBuffersLeft(0) {
}
- InFlightRequest(int id, int numBuffers) :
- requestId(id),
+ InFlightRequest(int numBuffers) :
captureTimestamp(0),
requestStatus(OK),
haveResultMetadata(false),
numBuffersLeft(numBuffers) {
}
+
+ InFlightRequest(int numBuffers, CaptureResultExtras extras) :
+ captureTimestamp(0),
+ requestStatus(OK),
+ haveResultMetadata(false),
+ numBuffersLeft(numBuffers),
+ resultExtras(extras) {
+ }
};
// Map from frame number to the in-flight request state
typedef KeyedVector<uint32_t, InFlightRequest> InFlightMap;
@@ -483,25 +529,25 @@ class Camera3Device :
Mutex mInFlightLock; // Protects mInFlightMap
InFlightMap mInFlightMap;
- status_t registerInFlight(int32_t frameNumber, int32_t requestId,
- int32_t numBuffers);
+ status_t registerInFlight(uint32_t frameNumber,
+ int32_t numBuffers, CaptureResultExtras resultExtras);
/**
* For the partial result quirk, check if all 3A state fields are available
* and if so, queue up 3A-only result to the client. Returns true if 3A
* is sent.
*/
- bool processPartial3AQuirk(int32_t frameNumber, int32_t requestId,
- const CameraMetadata& partial);
+ bool processPartial3AQuirk(uint32_t frameNumber,
+ const CameraMetadata& partial, const CaptureResultExtras& resultExtras);
// Helpers for reading and writing 3A metadata into to/from partial results
template<typename T>
bool get3AResult(const CameraMetadata& result, int32_t tag,
- T* value, int32_t frameNumber);
+ T* value, uint32_t frameNumber);
template<typename T>
bool insert3AResult(CameraMetadata &result, int32_t tag, const T* value,
- int32_t frameNumber);
+ uint32_t frameNumber);
/**
* Tracking for idle detection
*/
@@ -518,7 +564,7 @@ class Camera3Device :
uint32_t mNextResultFrameNumber;
uint32_t mNextShutterFrameNumber;
- List<CameraMetadata> mResultQueue;
+ List<CaptureResult> mResultQueue;
Condition mResultSignal;
NotificationListener *mListener;
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index d662cc2..50a2c10 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -34,7 +34,8 @@ Camera3IOStreamBase::Camera3IOStreamBase(int id, camera3_stream_type_t type,
Camera3Stream(id, type,
width, height, maxSize, format),
mTotalBufferCount(0),
- mDequeuedBufferCount(0),
+ mHandoutTotalBufferCount(0),
+ mHandoutOutputBufferCount(0),
mFrameCount(0),
mLastTimestamp(0) {
@@ -55,8 +56,8 @@ bool Camera3IOStreamBase::hasOutstandingBuffersLocked() const {
nsecs_t signalTime = mCombinedFence->getSignalTime();
ALOGV("%s: Stream %d: Has %zu outstanding buffers,"
" buffer signal time is %" PRId64,
- __FUNCTION__, mId, mDequeuedBufferCount, signalTime);
- if (mDequeuedBufferCount > 0 || signalTime == INT64_MAX) {
+ __FUNCTION__, mId, mHandoutTotalBufferCount, signalTime);
+ if (mHandoutTotalBufferCount > 0 || signalTime == INT64_MAX) {
return true;
}
return false;
@@ -75,7 +76,7 @@ void Camera3IOStreamBase::dump(int fd, const Vector<String16> &args) const {
lines.appendFormat(" Frames produced: %d, last timestamp: %" PRId64 " ns\n",
mFrameCount, mLastTimestamp);
lines.appendFormat(" Total buffers: %zu, currently dequeued: %zu\n",
- mTotalBufferCount, mDequeuedBufferCount);
+ mTotalBufferCount, mHandoutTotalBufferCount);
write(fd, lines.string(), lines.size());
}
@@ -104,6 +105,14 @@ size_t Camera3IOStreamBase::getBufferCountLocked() {
return mTotalBufferCount;
}
+size_t Camera3IOStreamBase::getHandoutOutputBufferCountLocked() {
+ return mHandoutOutputBufferCount;
+}
+
+size_t Camera3IOStreamBase::getHandoutInputBufferCountLocked() {
+ return (mHandoutTotalBufferCount - mHandoutOutputBufferCount);
+}
+
status_t Camera3IOStreamBase::disconnectLocked() {
switch (mState) {
case STATE_IN_RECONFIG:
@@ -117,9 +126,9 @@ status_t Camera3IOStreamBase::disconnectLocked() {
return -ENOTCONN;
}
- if (mDequeuedBufferCount > 0) {
+ if (mHandoutTotalBufferCount > 0) {
ALOGE("%s: Can't disconnect with %zu buffers still dequeued!",
- __FUNCTION__, mDequeuedBufferCount);
+ __FUNCTION__, mHandoutTotalBufferCount);
return INVALID_OPERATION;
}
@@ -130,7 +139,8 @@ void Camera3IOStreamBase::handoutBufferLocked(camera3_stream_buffer &buffer,
buffer_handle_t *handle,
int acquireFence,
int releaseFence,
- camera3_buffer_status_t status) {
+ camera3_buffer_status_t status,
+ bool output) {
/**
* Note that all fences are now owned by HAL.
*/
@@ -144,14 +154,25 @@ void Camera3IOStreamBase::handoutBufferLocked(camera3_stream_buffer &buffer,
buffer.status = status;
// Inform tracker about becoming busy
- if (mDequeuedBufferCount == 0 && mState != STATE_IN_CONFIG &&
+ if (mHandoutTotalBufferCount == 0 && mState != STATE_IN_CONFIG &&
mState != STATE_IN_RECONFIG) {
+ /**
+ * Avoid a spurious IDLE->ACTIVE->IDLE transition when using buffers
+ * before/after register_stream_buffers during initial configuration
+ * or re-configuration.
+ *
+ * TODO: IN_CONFIG and IN_RECONFIG checks only make sense for <HAL3.2
+ */
sp<StatusTracker> statusTracker = mStatusTracker.promote();
if (statusTracker != 0) {
statusTracker->markComponentActive(mStatusId);
}
}
- mDequeuedBufferCount++;
+ mHandoutTotalBufferCount++;
+
+ if (output) {
+ mHandoutOutputBufferCount++;
+ }
}
status_t Camera3IOStreamBase::getBufferPreconditionCheckLocked() const {
@@ -165,7 +186,7 @@ status_t Camera3IOStreamBase::getBufferPreconditionCheckLocked() const {
// Only limit dequeue amount when fully configured
if (mState == STATE_CONFIGURED &&
- mDequeuedBufferCount == camera3_stream::max_buffers) {
+ mHandoutTotalBufferCount == camera3_stream::max_buffers) {
ALOGE("%s: Stream %d: Already dequeued maximum number of simultaneous"
" buffers (%d)", __FUNCTION__, mId,
camera3_stream::max_buffers);
@@ -183,7 +204,7 @@ status_t Camera3IOStreamBase::returnBufferPreconditionCheckLocked() const {
__FUNCTION__, mId, mState);
return INVALID_OPERATION;
}
- if (mDequeuedBufferCount == 0) {
+ if (mHandoutTotalBufferCount == 0) {
ALOGE("%s: Stream %d: No buffers outstanding to return", __FUNCTION__,
mId);
return INVALID_OPERATION;
@@ -221,9 +242,20 @@ status_t Camera3IOStreamBase::returnAnyBufferLocked(
mCombinedFence = Fence::merge(mName, mCombinedFence, releaseFence);
}
- mDequeuedBufferCount--;
- if (mDequeuedBufferCount == 0 && mState != STATE_IN_CONFIG &&
+ if (output) {
+ mHandoutOutputBufferCount--;
+ }
+
+ mHandoutTotalBufferCount--;
+ if (mHandoutTotalBufferCount == 0 && mState != STATE_IN_CONFIG &&
mState != STATE_IN_RECONFIG) {
+ /**
+ * Avoid a spurious IDLE->ACTIVE->IDLE transition when using buffers
+ * before/after register_stream_buffers during initial configuration
+ * or re-configuration.
+ *
+ * TODO: IN_CONFIG and IN_RECONFIG checks only make sense for <HAL3.2
+ */
ALOGV("%s: Stream %d: All buffers returned; now idle", __FUNCTION__,
mId);
sp<StatusTracker> statusTracker = mStatusTracker.promote();
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index fcb9d04..a35c290 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -48,7 +48,10 @@ class Camera3IOStreamBase :
protected:
size_t mTotalBufferCount;
// sum of input and output buffers that are currently acquired by HAL
- size_t mDequeuedBufferCount;
+ size_t mHandoutTotalBufferCount;
+ // number of output buffers that are currently acquired by HAL. This will be
+ // Redundant when camera3 streams are no longer bidirectional streams.
+ size_t mHandoutOutputBufferCount;
Condition mBufferReturnedSignal;
uint32_t mFrameCount;
// Last received output buffer's timestamp
@@ -76,6 +79,10 @@ class Camera3IOStreamBase :
virtual size_t getBufferCountLocked();
+ virtual size_t getHandoutOutputBufferCountLocked();
+
+ virtual size_t getHandoutInputBufferCountLocked();
+
virtual status_t getEndpointUsage(uint32_t *usage) = 0;
status_t getBufferPreconditionCheckLocked() const;
@@ -92,7 +99,8 @@ class Camera3IOStreamBase :
buffer_handle_t *handle,
int acquire_fence,
int release_fence,
- camera3_buffer_status_t status);
+ camera3_buffer_status_t status,
+ bool output);
}; // class Camera3IOStreamBase
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index 5aa9a3e..319be1d 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -81,7 +81,7 @@ status_t Camera3InputStream::getInputBufferLocked(
* in which case we reassign it to acquire_fence
*/
handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
- /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK);
+ /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/false);
mBuffersInFlight.push_back(bufferItem);
return OK;
@@ -199,14 +199,36 @@ status_t Camera3InputStream::configureQueueLocked() {
assert(mMaxSize == 0);
assert(camera3_stream::format != HAL_PIXEL_FORMAT_BLOB);
- mTotalBufferCount = BufferQueue::MIN_UNDEQUEUED_BUFFERS +
- camera3_stream::max_buffers;
- mDequeuedBufferCount = 0;
+ mHandoutTotalBufferCount = 0;
mFrameCount = 0;
if (mConsumer.get() == 0) {
- sp<BufferQueue> bq = new BufferQueue();
- mConsumer = new BufferItemConsumer(bq, camera3_stream::usage,
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+
+ int minUndequeuedBuffers = 0;
+ res = producer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers);
+ if (res != OK || minUndequeuedBuffers < 0) {
+ ALOGE("%s: Stream %d: Could not query min undequeued buffers (error %d, bufCount %d)",
+ __FUNCTION__, mId, res, minUndequeuedBuffers);
+ return res;
+ }
+ size_t minBufs = static_cast<size_t>(minUndequeuedBuffers);
+ /*
+ * We promise never to 'acquire' more than camera3_stream::max_buffers
+ * at any one time.
+ *
+ * Boost the number up to meet the minimum required buffer count.
+ *
+ * (Note that this sets consumer-side buffer count only,
+ * and not the sum of producer+consumer side as in other camera streams).
+ */
+ mTotalBufferCount = camera3_stream::max_buffers > minBufs ?
+ camera3_stream::max_buffers : minBufs;
+ // TODO: somehow set the total buffer count when producer connects?
+
+ mConsumer = new BufferItemConsumer(consumer, camera3_stream::usage,
mTotalBufferCount);
mConsumer->setName(String8::format("Camera3-InputStream-%d", mId));
}
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.h b/services/camera/libcameraservice/device3/Camera3InputStream.h
index 681d684..ae49467 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.h
@@ -44,6 +44,8 @@ class Camera3InputStream : public Camera3IOStreamBase {
virtual void dump(int fd, const Vector<String16> &args) const;
+ // TODO: expose an interface to get the IGraphicBufferProducer
+
private:
typedef BufferItemConsumer::BufferItem BufferItem;
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 682755d..7ec649b 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -119,7 +119,7 @@ status_t Camera3OutputStream::getBufferLocked(camera3_stream_buffer *buffer) {
* in which case we reassign it to acquire_fence
*/
handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
- /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK);
+ /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/true);
return OK;
}
@@ -324,7 +324,7 @@ status_t Camera3OutputStream::configureQueueLocked() {
}
mTotalBufferCount = maxConsumerBuffers + camera3_stream::max_buffers;
- mDequeuedBufferCount = 0;
+ mHandoutTotalBufferCount = 0;
mFrameCount = 0;
mLastTimestamp = 0;
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 70406f1..7645a2a 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -23,6 +23,8 @@
#include "device3/Camera3Stream.h"
#include "device3/StatusTracker.h"
+#include <cutils/properties.h>
+
namespace android {
namespace camera3 {
@@ -137,6 +139,7 @@ camera3_stream* Camera3Stream::startConfiguration() {
if (mState == STATE_CONSTRUCTED) {
mState = STATE_IN_CONFIG;
} else { // mState == STATE_CONFIGURED
+ LOG_ALWAYS_FATAL_IF(mState != STATE_CONFIGURED, "Invalid state: 0x%x", mState);
mState = STATE_IN_RECONFIG;
}
@@ -209,8 +212,30 @@ status_t Camera3Stream::finishConfiguration(camera3_device *hal3Device) {
status_t Camera3Stream::getBuffer(camera3_stream_buffer *buffer) {
ATRACE_CALL();
Mutex::Autolock l(mLock);
+ status_t res = OK;
+
+ // This function should be only called when the stream is configured already.
+ if (mState != STATE_CONFIGURED) {
+ ALOGE("%s: Stream %d: Can't get buffers if stream is not in CONFIGURED state %d",
+ __FUNCTION__, mId, mState);
+ return INVALID_OPERATION;
+ }
+
+ // Wait for new buffer returned back if we are running into the limit.
+ if (getHandoutOutputBufferCountLocked() == camera3_stream::max_buffers) {
+ ALOGV("%s: Already dequeued max output buffers (%d), wait for next returned one.",
+ __FUNCTION__, camera3_stream::max_buffers);
+ res = mOutputBufferReturnedSignal.waitRelative(mLock, kWaitForBufferDuration);
+ if (res != OK) {
+ if (res == TIMED_OUT) {
+ ALOGE("%s: wait for output buffer return timed out after %lldms", __FUNCTION__,
+ kWaitForBufferDuration / 1000000LL);
+ }
+ return res;
+ }
+ }
- status_t res = getBufferLocked(buffer);
+ res = getBufferLocked(buffer);
if (res == OK) {
fireBufferListenersLocked(*buffer, /*acquired*/true, /*output*/true);
}
@@ -223,9 +248,18 @@ status_t Camera3Stream::returnBuffer(const camera3_stream_buffer &buffer,
ATRACE_CALL();
Mutex::Autolock l(mLock);
+ /**
+ * TODO: Check that the state is valid first.
+ *
+ * <HAL3.2 IN_CONFIG and IN_RECONFIG in addition to CONFIGURED.
+ * >= HAL3.2 CONFIGURED only
+ *
+ * Do this for getBuffer as well.
+ */
status_t res = returnBufferLocked(buffer, timestamp);
if (res == OK) {
fireBufferListenersLocked(buffer, /*acquired*/false, /*output*/true);
+ mOutputBufferReturnedSignal.signal();
}
return res;
@@ -234,8 +268,30 @@ status_t Camera3Stream::returnBuffer(const camera3_stream_buffer &buffer,
status_t Camera3Stream::getInputBuffer(camera3_stream_buffer *buffer) {
ATRACE_CALL();
Mutex::Autolock l(mLock);
+ status_t res = OK;
+
+ // This function should be only called when the stream is configured already.
+ if (mState != STATE_CONFIGURED) {
+ ALOGE("%s: Stream %d: Can't get input buffers if stream is not in CONFIGURED state %d",
+ __FUNCTION__, mId, mState);
+ return INVALID_OPERATION;
+ }
+
+ // Wait for new buffer returned back if we are running into the limit.
+ if (getHandoutInputBufferCountLocked() == camera3_stream::max_buffers) {
+ ALOGV("%s: Already dequeued max input buffers (%d), wait for next returned one.",
+ __FUNCTION__, camera3_stream::max_buffers);
+ res = mInputBufferReturnedSignal.waitRelative(mLock, kWaitForBufferDuration);
+ if (res != OK) {
+ if (res == TIMED_OUT) {
+ ALOGE("%s: wait for input buffer return timed out after %lldms", __FUNCTION__,
+ kWaitForBufferDuration / 1000000LL);
+ }
+ return res;
+ }
+ }
- status_t res = getInputBufferLocked(buffer);
+ res = getInputBufferLocked(buffer);
if (res == OK) {
fireBufferListenersLocked(*buffer, /*acquired*/true, /*output*/false);
}
@@ -250,6 +306,7 @@ status_t Camera3Stream::returnInputBuffer(const camera3_stream_buffer &buffer) {
status_t res = returnInputBufferLocked(buffer);
if (res == OK) {
fireBufferListenersLocked(buffer, /*acquired*/false, /*output*/false);
+ mInputBufferReturnedSignal.signal();
}
return res;
}
@@ -314,12 +371,46 @@ status_t Camera3Stream::disconnect() {
status_t Camera3Stream::registerBuffersLocked(camera3_device *hal3Device) {
ATRACE_CALL();
+
+ /**
+ * >= CAMERA_DEVICE_API_VERSION_3_2:
+ *
+ * camera3_device_t->ops->register_stream_buffers() is not called and must
+ * be NULL.
+ */
+ if (hal3Device->common.version >= CAMERA_DEVICE_API_VERSION_3_2) {
+ ALOGV("%s: register_stream_buffers unused as of HAL3.2", __FUNCTION__);
+
+ /**
+ * Skip the NULL check if camera.dev.register_stream is 1.
+ *
+ * For development-validation purposes only.
+ *
+ * TODO: Remove the property check before shipping L (b/13914251).
+ */
+ char value[PROPERTY_VALUE_MAX] = { '\0', };
+ property_get("camera.dev.register_stream", value, "0");
+ int propInt = atoi(value);
+
+ if (propInt == 0 && hal3Device->ops->register_stream_buffers != NULL) {
+ ALOGE("%s: register_stream_buffers is deprecated in HAL3.2; "
+ "must be set to NULL in camera3_device::ops", __FUNCTION__);
+ return INVALID_OPERATION;
+ } else {
+ ALOGD("%s: Skipping NULL check for deprecated register_stream_buffers", __FUNCTION__);
+ }
+
+ return OK;
+ } else {
+ ALOGV("%s: register_stream_buffers using deprecated code path", __FUNCTION__);
+ }
+
status_t res;
size_t bufferCount = getBufferCountLocked();
Vector<buffer_handle_t*> buffers;
- buffers.insertAt(NULL, 0, bufferCount);
+ buffers.insertAt(/*prototype_item*/NULL, /*index*/0, bufferCount);
camera3_stream_buffer_set bufferSet = camera3_stream_buffer_set();
bufferSet.stream = this;
@@ -327,7 +418,7 @@ status_t Camera3Stream::registerBuffersLocked(camera3_device *hal3Device) {
bufferSet.buffers = buffers.editArray();
Vector<camera3_stream_buffer_t> streamBuffers;
- streamBuffers.insertAt(camera3_stream_buffer_t(), 0, bufferCount);
+ streamBuffers.insertAt(camera3_stream_buffer_t(), /*index*/0, bufferCount);
// Register all buffers with the HAL. This means getting all the buffers
// from the stream, providing them to the HAL with the
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 6eeb721..14f5387 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -82,6 +82,23 @@ namespace camera3 {
* STATE_CONFIGURED => STATE_CONSTRUCTED:
* When disconnect() is called after making sure stream is idle with
* waitUntilIdle().
+ *
+ * Status Tracking:
+ * Each stream is tracked by StatusTracker as a separate component,
+ * depending on the handed out buffer count. The state must be STATE_CONFIGURED
+ * in order for the component to be marked.
+ *
+ * It's marked in one of two ways:
+ *
+ * - ACTIVE: One or more buffers have been handed out (with #getBuffer).
+ * - IDLE: All buffers have been returned (with #returnBuffer), and their
+ * respective release_fence(s) have been signaled.
+ *
+ * A typical use case is output streams. When the HAL has any buffers
+ * dequeued, the stream is marked ACTIVE. When the HAL returns all buffers
+ * (e.g. if no capture requests are active), the stream is marked IDLE.
+ * In this use case, the app consumer does not affect the component status.
+ *
*/
class Camera3Stream :
protected camera3_stream,
@@ -262,6 +279,12 @@ class Camera3Stream :
// Get the total number of buffers in the queue
virtual size_t getBufferCountLocked() = 0;
+ // Get handout output buffer count.
+ virtual size_t getHandoutOutputBufferCountLocked() = 0;
+
+ // Get handout input buffer count.
+ virtual size_t getHandoutInputBufferCountLocked() = 0;
+
// Get the usage flags for the other endpoint, or return
// INVALID_OPERATION if they cannot be obtained.
virtual status_t getEndpointUsage(uint32_t *usage) = 0;
@@ -274,6 +297,9 @@ class Camera3Stream :
private:
uint32_t oldUsage;
uint32_t oldMaxBuffers;
+ Condition mOutputBufferReturnedSignal;
+ Condition mInputBufferReturnedSignal;
+ static const nsecs_t kWaitForBufferDuration = 3000000000LL; // 3000 ms
// Gets all buffers from endpoint and registers them with the HAL.
status_t registerBuffersLocked(camera3_device *hal3Device);
diff --git a/services/camera/libcameraservice/device3/Camera3ZslStream.cpp b/services/camera/libcameraservice/device3/Camera3ZslStream.cpp
index 44d8188..05b3d1f 100644
--- a/services/camera/libcameraservice/device3/Camera3ZslStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3ZslStream.cpp
@@ -111,15 +111,17 @@ struct TimestampFinder : public RingBufferConsumer::RingBufferComparator {
} // namespace anonymous
Camera3ZslStream::Camera3ZslStream(int id, uint32_t width, uint32_t height,
- int depth) :
+ int bufferCount) :
Camera3OutputStream(id, CAMERA3_STREAM_BIDIRECTIONAL,
width, height,
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
- mDepth(depth) {
+ mDepth(bufferCount) {
- sp<BufferQueue> bq = new BufferQueue();
- mProducer = new RingBufferConsumer(bq, GRALLOC_USAGE_HW_CAMERA_ZSL, depth);
- mConsumer = new Surface(bq);
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ mProducer = new RingBufferConsumer(consumer, GRALLOC_USAGE_HW_CAMERA_ZSL, bufferCount);
+ mConsumer = new Surface(producer);
}
Camera3ZslStream::~Camera3ZslStream() {
@@ -174,7 +176,7 @@ status_t Camera3ZslStream::getInputBufferLocked(camera3_stream_buffer *buffer) {
* in which case we reassign it to acquire_fence
*/
handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
- /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK);
+ /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/false);
mBuffersInFlight.push_back(bufferItem);
diff --git a/services/camera/libcameraservice/device3/Camera3ZslStream.h b/services/camera/libcameraservice/device3/Camera3ZslStream.h
index c7f4490..6721832 100644
--- a/services/camera/libcameraservice/device3/Camera3ZslStream.h
+++ b/services/camera/libcameraservice/device3/Camera3ZslStream.h
@@ -37,10 +37,10 @@ class Camera3ZslStream :
public Camera3OutputStream {
public:
/**
- * Set up a ZSL stream of a given resolution. Depth is the number of buffers
+ * Set up a ZSL stream of a given resolution. bufferCount is the number of buffers
* cached within the stream that can be retrieved for input.
*/
- Camera3ZslStream(int id, uint32_t width, uint32_t height, int depth);
+ Camera3ZslStream(int id, uint32_t width, uint32_t height, int bufferCount);
~Camera3ZslStream();
virtual void dump(int fd, const Vector<String16> &args) const;