diff options
Diffstat (limited to 'services/camera/libcameraservice')
10 files changed, 170 insertions, 75 deletions
diff --git a/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp b/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp index 3de5d90..312a78c 100644 --- a/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp +++ b/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp @@ -40,7 +40,12 @@ FrameProcessor::FrameProcessor(wp<CameraDeviceBase> device, { SharedParameters::Lock l(client->getParameters()); - mUsePartialQuirk = l.mParameters.quirks.partialResults; + + if (client->getCameraDeviceVersion() >= CAMERA_DEVICE_API_VERSION_3_2) { + mUsePartialResult = (mNumPartialResults > 1); + } else { + mUsePartialResult = l.mParameters.quirks.partialResults; + } // Initialize starting 3A state m3aState.afTriggerId = l.mParameters.afTriggerCounter; @@ -63,17 +68,21 @@ bool FrameProcessor::processSingleFrame(CaptureResult &frame, return false; } - bool partialResult = false; - if (mUsePartialQuirk) { - camera_metadata_entry_t entry; - entry = frame.mMetadata.find(ANDROID_QUIRKS_PARTIAL_RESULT); - if (entry.count > 0 && - entry.data.u8[0] == ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL) { - partialResult = true; + bool isPartialResult = false; + if (mUsePartialResult) { + if (client->getCameraDeviceVersion() >= CAMERA_DEVICE_API_VERSION_3_2) { + isPartialResult = frame.mResultExtras.partialResultCount < mNumPartialResults; + } else { + camera_metadata_entry_t entry; + entry = frame.mMetadata.find(ANDROID_QUIRKS_PARTIAL_RESULT); + if (entry.count > 0 && + entry.data.u8[0] == ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL) { + isPartialResult = true; + } } } - if (!partialResult && processFaceDetect(frame.mMetadata, client) != OK) { + if (!isPartialResult && processFaceDetect(frame.mMetadata, client) != OK) { return false; } diff --git a/services/camera/libcameraservice/api1/client2/FrameProcessor.h b/services/camera/libcameraservice/api1/client2/FrameProcessor.h index 4afca50..68cf55b 100644 --- a/services/camera/libcameraservice/api1/client2/FrameProcessor.h +++ b/services/camera/libcameraservice/api1/client2/FrameProcessor.h @@ -91,8 +91,8 @@ class FrameProcessor : public FrameProcessorBase { } } m3aState; - // Whether the partial result quirk is enabled for this device - bool mUsePartialQuirk; + // Whether the partial result is enabled for this device + bool mUsePartialResult; // Track most recent frame number for which 3A notifications were sent for. // Used to filter against sending 3A notifications for the same frame diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp index 79f75a5..ab61c44 100644 --- a/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp +++ b/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp @@ -94,14 +94,14 @@ void ZslProcessor3::onResultAvailable(const CaptureResult &result) { entry = result.mMetadata.find(ANDROID_SENSOR_TIMESTAMP); nsecs_t timestamp = entry.data.i64[0]; if (entry.count == 0) { - ALOGE("%s: metadata doesn't have timestamp, skip this result"); + ALOGE("%s: metadata doesn't have timestamp, skip this result", __FUNCTION__); return; } (void)timestamp; entry = result.mMetadata.find(ANDROID_REQUEST_FRAME_COUNT); if (entry.count == 0) { - ALOGE("%s: metadata doesn't have frame number, skip this result"); + ALOGE("%s: metadata doesn't have frame number, skip this result", __FUNCTION__); return; } int32_t frameNumber = entry.data.i32[0]; diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h index c7bd886..037695d 100644 --- a/services/camera/libcameraservice/common/CameraDeviceBase.h +++ b/services/camera/libcameraservice/common/CameraDeviceBase.h @@ -252,6 +252,10 @@ class CameraDeviceBase : public virtual RefBase { */ virtual status_t flush(int64_t *lastFrameNumber = NULL) = 0; + /** + * Get the HAL device version. + */ + virtual uint32_t getDeviceVersion() = 0; }; }; // namespace android diff --git a/services/camera/libcameraservice/common/FrameProcessorBase.cpp b/services/camera/libcameraservice/common/FrameProcessorBase.cpp index 482f687..29eb78f 100644 --- a/services/camera/libcameraservice/common/FrameProcessorBase.cpp +++ b/services/camera/libcameraservice/common/FrameProcessorBase.cpp @@ -29,7 +29,17 @@ namespace camera2 { FrameProcessorBase::FrameProcessorBase(wp<CameraDeviceBase> device) : Thread(/*canCallJava*/false), - mDevice(device) { + mDevice(device), + mNumPartialResults(1) { + sp<CameraDeviceBase> cameraDevice = device.promote(); + if (cameraDevice != 0 && + cameraDevice->getDeviceVersion() >= CAMERA_DEVICE_API_VERSION_3_2) { + CameraMetadata staticInfo = cameraDevice->info(); + camera_metadata_entry_t entry = staticInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT); + if (entry.count > 0) { + mNumPartialResults = entry.data.i32[0]; + } + } } FrameProcessorBase::~FrameProcessorBase() { @@ -160,14 +170,18 @@ status_t FrameProcessorBase::processListeners(const CaptureResult &result, camera_metadata_ro_entry_t entry; - // Quirks: Don't deliver partial results to listeners that don't want them - bool quirkIsPartial = false; - entry = result.mMetadata.find(ANDROID_QUIRKS_PARTIAL_RESULT); - if (entry.count != 0 && - entry.data.u8[0] == ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL) { - ALOGV("%s: Camera %d: Not forwarding partial result to listeners", - __FUNCTION__, device->getId()); - quirkIsPartial = true; + // Check if this result is partial. + bool isPartialResult = false; + if (device->getDeviceVersion() >= CAMERA_DEVICE_API_VERSION_3_2) { + isPartialResult = result.mResultExtras.partialResultCount < mNumPartialResults; + } else { + entry = result.mMetadata.find(ANDROID_QUIRKS_PARTIAL_RESULT); + if (entry.count != 0 && + entry.data.u8[0] == ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL) { + ALOGV("%s: Camera %d: This is a partial result", + __FUNCTION__, device->getId()); + isPartialResult = true; + } } // TODO: instead of getting requestID from CameraMetadata, we should get it @@ -186,9 +200,10 @@ status_t FrameProcessorBase::processListeners(const CaptureResult &result, Mutex::Autolock l(mInputMutex); List<RangeListener>::iterator item = mRangeListeners.begin(); + // Don't deliver partial results to listeners that don't want them while (item != mRangeListeners.end()) { if (requestId >= item->minId && requestId < item->maxId && - (!quirkIsPartial || item->sendPartials)) { + (!isPartialResult || item->sendPartials)) { sp<FilteredListener> listener = item->listener.promote(); if (listener == 0) { item = mRangeListeners.erase(item); diff --git a/services/camera/libcameraservice/common/FrameProcessorBase.h b/services/camera/libcameraservice/common/FrameProcessorBase.h index 3649c45..a618d84 100644 --- a/services/camera/libcameraservice/common/FrameProcessorBase.h +++ b/services/camera/libcameraservice/common/FrameProcessorBase.h @@ -71,6 +71,9 @@ class FrameProcessorBase: public Thread { }; List<RangeListener> mRangeListeners; + // Number of partial result the HAL will potentially send. + int32_t mNumPartialResults; + void processNewFrames(const sp<CameraDeviceBase> &device); virtual bool processSingleFrame(CaptureResult &result, diff --git a/services/camera/libcameraservice/device2/Camera2Device.cpp b/services/camera/libcameraservice/device2/Camera2Device.cpp index c33c166..89c6b10 100644 --- a/services/camera/libcameraservice/device2/Camera2Device.cpp +++ b/services/camera/libcameraservice/device2/Camera2Device.cpp @@ -123,6 +123,7 @@ status_t Camera2Device::initialize(camera_module_t *module) mDeviceInfo = info.static_camera_characteristics; mHal2Device = device; + mDeviceVersion = device->common.version; return OK; } @@ -589,6 +590,11 @@ status_t Camera2Device::flush(int64_t* /*lastFrameNumber*/) { return waitUntilDrained(); } +uint32_t Camera2Device::getDeviceVersion() { + ATRACE_CALL(); + return mDeviceVersion; +} + /** * Camera2Device::MetadataQueue */ diff --git a/services/camera/libcameraservice/device2/Camera2Device.h b/services/camera/libcameraservice/device2/Camera2Device.h index 22a13ac..46182f8 100644 --- a/services/camera/libcameraservice/device2/Camera2Device.h +++ b/services/camera/libcameraservice/device2/Camera2Device.h @@ -78,12 +78,16 @@ class Camera2Device: public CameraDeviceBase { buffer_handle_t *buffer, wp<BufferReleasedListener> listener); // Flush implemented as just a wait virtual status_t flush(int64_t *lastFrameNumber = NULL); + virtual uint32_t getDeviceVersion(); + private: const int mId; camera2_device_t *mHal2Device; CameraMetadata mDeviceInfo; + uint32_t mDeviceVersion; + /** * Queue class for both sending requests to a camera2 device, and for * receiving frames from a camera2 device. diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 6ceb9d4..3004d3e 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -57,7 +57,8 @@ Camera3Device::Camera3Device(int id): mId(id), mHal3Device(NULL), mStatus(STATUS_UNINITIALIZED), - mUsePartialResultQuirk(false), + mUsePartialResult(false), + mNumPartialResults(1), mNextResultFrameNumber(0), mNextShutterFrameNumber(0), mListener(NULL) @@ -180,13 +181,20 @@ status_t Camera3Device::initialize(camera_module_t *module) mNeedConfig = true; mPauseStateNotify = false; - /** Check for quirks */ - // Will the HAL be sending in early partial result metadata? - camera_metadata_entry partialResultsQuirk = - mDeviceInfo.find(ANDROID_QUIRKS_USE_PARTIAL_RESULT); - if (partialResultsQuirk.count > 0 && partialResultsQuirk.data.u8[0] == 1) { - mUsePartialResultQuirk = true; + if (mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_2) { + camera_metadata_entry partialResultsCount = + mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT); + if (partialResultsCount.count > 0) { + mNumPartialResults = partialResultsCount.data.i32[0]; + mUsePartialResult = (mNumPartialResults > 1); + } + } else { + camera_metadata_entry partialResultsQuirk = + mDeviceInfo.find(ANDROID_QUIRKS_USE_PARTIAL_RESULT); + if (partialResultsQuirk.count > 0 && partialResultsQuirk.data.u8[0] == 1) { + mUsePartialResult = true; + } } return OK; @@ -1267,6 +1275,12 @@ status_t Camera3Device::flush(int64_t *frameNumber) { return res; } +uint32_t Camera3Device::getDeviceVersion() { + ATRACE_CALL(); + Mutex::Autolock il(mInterfaceLock); + return mDeviceVersion; +} + /** * Methods called by subclasses */ @@ -1545,11 +1559,10 @@ status_t Camera3Device::registerInFlight(uint32_t frameNumber, } /** - * QUIRK(partial results) * Check if all 3A fields are ready, and send off a partial 3A-only result * to the output frame queue */ -bool Camera3Device::processPartial3AQuirk( +bool Camera3Device::processPartial3AResult( uint32_t frameNumber, const CameraMetadata& partial, const CaptureResultExtras& resultExtras) { @@ -1601,7 +1614,7 @@ bool Camera3Device::processPartial3AQuirk( // In addition to the above fields, this means adding in // android.request.frameCount // android.request.requestId - // android.quirks.partialResult + // android.quirks.partialResult (for HAL version below HAL3.2) const size_t kMinimal3AResultEntries = 10; @@ -1627,10 +1640,12 @@ bool Camera3Device::processPartial3AQuirk( return false; } - static const uint8_t partialResult = ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL; - if (!insert3AResult(min3AResult.mMetadata, ANDROID_QUIRKS_PARTIAL_RESULT, - &partialResult, frameNumber)) { - return false; + if (mDeviceVersion < CAMERA_DEVICE_API_VERSION_3_2) { + static const uint8_t partialResult = ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL; + if (!insert3AResult(min3AResult.mMetadata, ANDROID_QUIRKS_PARTIAL_RESULT, + &partialResult, frameNumber)) { + return false; + } } if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AF_MODE, @@ -1668,6 +1683,9 @@ bool Camera3Device::processPartial3AQuirk( return false; } + // We only send the aggregated partial when all 3A related metadata are available + // For both API1 and API2. + // TODO: we probably should pass through all partials to API2 unconditionally. mResultSignal.signal(); return true; @@ -1726,8 +1744,21 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) { frameNumber); return; } - bool partialResultQuirk = false; - CameraMetadata collectedQuirkResult; + + // For HAL3.2 or above, If HAL doesn't support partial, it must always set + // partial_result to 1 when metadata is included in this result. + if (!mUsePartialResult && + mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_2 && + result->result != NULL && + result->partial_result != 1) { + SET_ERR("Result is malformed for frame %d: partial_result %u must be 1" + " if partial result is not supported", + frameNumber, result->partial_result); + return; + } + + bool isPartialResult = false; + CameraMetadata collectedPartialResult; CaptureResultExtras resultExtras; bool hasInputBufferInRequest = false; @@ -1749,28 +1780,46 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) { ", burstId = %" PRId32, __FUNCTION__, request.resultExtras.requestId, request.resultExtras.frameNumber, request.resultExtras.burstId); + // Always update the partial count to the latest one. When framework aggregates adjacent + // partial results into one, the latest partial count will be used. + request.resultExtras.partialResultCount = result->partial_result; // Check if this result carries only partial metadata - if (mUsePartialResultQuirk && result->result != NULL) { - camera_metadata_ro_entry_t partialResultEntry; - res = find_camera_metadata_ro_entry(result->result, - ANDROID_QUIRKS_PARTIAL_RESULT, &partialResultEntry); - if (res != NAME_NOT_FOUND && - partialResultEntry.count > 0 && - partialResultEntry.data.u8[0] == - ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL) { - // A partial result. Flag this as such, and collect this - // set of metadata into the in-flight entry. - partialResultQuirk = true; - request.partialResultQuirk.collectedResult.append( + if (mUsePartialResult && result->result != NULL) { + if (mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_2) { + if (result->partial_result > mNumPartialResults || result->partial_result < 1) { + SET_ERR("Result is malformed for frame %d: partial_result %u must be in" + " the range of [1, %d] when metadata is included in the result", + frameNumber, result->partial_result, mNumPartialResults); + return; + } + isPartialResult = (result->partial_result < mNumPartialResults); + request.partialResult.collectedResult.append( result->result); - request.partialResultQuirk.collectedResult.erase( - ANDROID_QUIRKS_PARTIAL_RESULT); + } else { + camera_metadata_ro_entry_t partialResultEntry; + res = find_camera_metadata_ro_entry(result->result, + ANDROID_QUIRKS_PARTIAL_RESULT, &partialResultEntry); + if (res != NAME_NOT_FOUND && + partialResultEntry.count > 0 && + partialResultEntry.data.u8[0] == + ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL) { + // A partial result. Flag this as such, and collect this + // set of metadata into the in-flight entry. + isPartialResult = true; + request.partialResult.collectedResult.append( + result->result); + request.partialResult.collectedResult.erase( + ANDROID_QUIRKS_PARTIAL_RESULT); + } + } + + if (isPartialResult) { // Fire off a 3A-only result if possible - if (!request.partialResultQuirk.haveSent3A) { - request.partialResultQuirk.haveSent3A = - processPartial3AQuirk(frameNumber, - request.partialResultQuirk.collectedResult, + if (!request.partialResult.haveSent3A) { + request.partialResult.haveSent3A = + processPartial3AResult(frameNumber, + request.partialResult.collectedResult, request.resultExtras); } } @@ -1786,23 +1835,23 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) { * - CAMERA3_MSG_SHUTTER (expected during normal operation) * - CAMERA3_MSG_ERROR (expected during flush) */ - if (request.requestStatus == OK && timestamp == 0 && !partialResultQuirk) { + if (request.requestStatus == OK && timestamp == 0 && !isPartialResult) { SET_ERR("Called before shutter notify for frame %d", frameNumber); return; } // Did we get the (final) result metadata for this capture? - if (result->result != NULL && !partialResultQuirk) { + if (result->result != NULL && !isPartialResult) { if (request.haveResultMetadata) { SET_ERR("Called multiple times with metadata for frame %d", frameNumber); return; } - if (mUsePartialResultQuirk && - !request.partialResultQuirk.collectedResult.isEmpty()) { - collectedQuirkResult.acquire( - request.partialResultQuirk.collectedResult); + if (mUsePartialResult && + !request.partialResult.collectedResult.isEmpty()) { + collectedPartialResult.acquire( + request.partialResult.collectedResult); } request.haveResultMetadata = true; } @@ -1842,7 +1891,7 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) { // Process the result metadata, if provided bool gotResult = false; - if (result->result != NULL && !partialResultQuirk) { + if (result->result != NULL && !isPartialResult) { Mutex::Autolock l(mOutputLock); gotResult = true; @@ -1871,8 +1920,8 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) { } // Append any previous partials to form a complete result - if (mUsePartialResultQuirk && !collectedQuirkResult.isEmpty()) { - captureResult.mMetadata.append(collectedQuirkResult); + if (mUsePartialResult && !collectedPartialResult.isEmpty()) { + captureResult.mMetadata.append(collectedPartialResult); } captureResult.mMetadata.sort(); diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h index ea958b7..b1b0033 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.h +++ b/services/camera/libcameraservice/device3/Camera3Device.h @@ -135,6 +135,8 @@ class Camera3Device : virtual status_t flush(int64_t *lastFrameNumber = NULL); + virtual uint32_t getDeviceVersion(); + // Methods called by subclasses void notifyStatus(bool idle); // updates from StatusTracker @@ -168,7 +170,7 @@ class Camera3Device : CameraMetadata mDeviceInfo; - int mDeviceVersion; + uint32_t mDeviceVersion; enum Status { STATUS_ERROR, @@ -199,8 +201,11 @@ class Camera3Device : // Need to hold on to stream references until configure completes. Vector<sp<camera3::Camera3StreamInterface> > mDeletedStreams; - // Whether quirk ANDROID_QUIRKS_USE_PARTIAL_RESULT is enabled - bool mUsePartialResultQuirk; + // Whether the HAL will send partial result + bool mUsePartialResult; + + // Number of partial results that will be delivered by the HAL. + uint32_t mNumPartialResults; /**** End scope for mLock ****/ @@ -507,17 +512,17 @@ class Camera3Device : // If this request has any input buffer bool hasInputBuffer; - // Fields used by the partial result quirk only - struct PartialResultQuirkInFlight { + // Fields used by the partial result only + struct PartialResultInFlight { // Set by process_capture_result once 3A has been sent to clients bool haveSent3A; // Result metadata collected so far, when partial results are in use CameraMetadata collectedResult; - PartialResultQuirkInFlight(): + PartialResultInFlight(): haveSent3A(false) { } - } partialResultQuirk; + } partialResult; // Default constructor needed by KeyedVector InFlightRequest() : @@ -564,11 +569,11 @@ class Camera3Device : int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput); /** - * For the partial result quirk, check if all 3A state fields are available + * For the partial result, 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(uint32_t frameNumber, + bool processPartial3AResult(uint32_t frameNumber, const CameraMetadata& partial, const CaptureResultExtras& resultExtras); // Helpers for reading and writing 3A metadata into to/from partial results |