diff options
Diffstat (limited to 'services/camera/libcameraservice/device3/Camera3Device.cpp')
-rw-r--r-- | services/camera/libcameraservice/device3/Camera3Device.cpp | 478 |
1 files changed, 328 insertions, 150 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; } |