Camera: Wait until the current request id appears in the results

Camera preview stop only waits until the
current capture request is sent to Hal and
then immediately flushes the device.
Depending on timing and the pending request
queue size within CameraHal the current camera
client parameters may get flushed before
they are able to reach the end of the
processing pipeline.
Avoid this by waiting for the current request
id to appear in the incoming results.

Bug: 139330668
Test: Camera CTS, manual using application

Change-Id: I18de85557e8e76bfbe6d69b1eb2a5c36ed64e803
gugelfrei
Emilian Peev 5 years ago
parent ef61973b8c
commit 2a8e283839

@ -959,6 +959,11 @@ void Camera2Client::stopPreviewL() {
case Parameters::RECORD:
case Parameters::PREVIEW:
syncWithDevice();
// Due to flush a camera device sync is not a sufficient
// guarantee that the current client parameters are
// correctly applied. To resolve this wait for the current
// request id to return in the results.
waitUntilCurrentRequestIdLocked();
res = stopStream();
if (res != OK) {
ALOGE("%s: Camera %d: Can't stop streaming: %s (%d)",
@ -2259,6 +2264,46 @@ int32_t Camera2Client::setAudioRestriction(int /*mode*/) {
return INVALID_OPERATION;
}
status_t Camera2Client::waitUntilCurrentRequestIdLocked() {
int32_t activeRequestId = mStreamingProcessor->getActiveRequestId();
if (activeRequestId != 0) {
auto res = waitUntilRequestIdApplied(activeRequestId,
mDevice->getExpectedInFlightDuration());
if (res == TIMED_OUT) {
ALOGE("%s: Camera %d: Timed out waiting for current request id to return in results!",
__FUNCTION__, mCameraId);
return res;
} else if (res != OK) {
ALOGE("%s: Camera %d: Error while waiting for current request id to return in results!",
__FUNCTION__, mCameraId);
return res;
}
}
return OK;
}
status_t Camera2Client::waitUntilRequestIdApplied(int32_t requestId, nsecs_t timeout) {
Mutex::Autolock l(mLatestRequestMutex);
while (mLatestRequestId != requestId) {
nsecs_t startTime = systemTime();
auto res = mLatestRequestSignal.waitRelative(mLatestRequestMutex, timeout);
if (res != OK) return res;
timeout -= (systemTime() - startTime);
}
return OK;
}
void Camera2Client::notifyRequestId(int32_t requestId) {
Mutex::Autolock al(mLatestRequestMutex);
mLatestRequestId = requestId;
mLatestRequestSignal.signal();
}
const char* Camera2Client::kAutofocusLabel = "autofocus";
const char* Camera2Client::kTakepictureLabel = "take_picture";

@ -123,6 +123,8 @@ public:
camera2::SharedParameters& getParameters();
void notifyRequestId(int32_t requestId);
int getPreviewStreamId() const;
int getCaptureStreamId() const;
int getCallbackStreamId() const;
@ -228,6 +230,12 @@ private:
status_t initializeImpl(TProviderPtr providerPtr, const String8& monitorTags);
bool isZslEnabledInStillTemplate();
mutable Mutex mLatestRequestMutex;
Condition mLatestRequestSignal;
int32_t mLatestRequestId = -1;
status_t waitUntilRequestIdApplied(int32_t requestId, nsecs_t timeout);
status_t waitUntilCurrentRequestIdLocked();
};
}; // namespace android

@ -86,6 +86,12 @@ bool FrameProcessor::processSingleFrame(CaptureResult &frame,
process3aState(frame, client);
}
if (mCurrentRequestId != frame.mResultExtras.requestId) {
mCurrentRequestId = frame.mResultExtras.requestId;
client->notifyRequestId(mCurrentRequestId);
}
return FrameProcessorBase::processSingleFrame(frame, device);
}

@ -94,6 +94,7 @@ class FrameProcessor : public FrameProcessorBase {
};
AlgState m3aState;
int32_t mCurrentRequestId = -1;
// frame number -> pending 3A states that not all data are received yet.
KeyedVector<int32_t, AlgState> mPending3AStates;

@ -383,6 +383,12 @@ class CameraDeviceBase : public virtual RefBase {
* drop buffers for stream of streamId.
*/
virtual status_t dropStreamBuffers(bool /*dropping*/, int /*streamId*/) = 0;
/**
* Returns the maximum expected time it'll take for all currently in-flight
* requests to complete, based on their settings
*/
virtual nsecs_t getExpectedInFlightDuration() = 0;
};
}; // namespace android

@ -194,6 +194,8 @@ class Camera3Device :
*/
status_t dropStreamBuffers(bool dropping, int streamId) override;
nsecs_t getExpectedInFlightDuration() override;
/**
* Helper functions to map between framework and HIDL values
*/
@ -1110,12 +1112,6 @@ class Camera3Device :
bool isStillCapture, bool isZslCapture,
const SurfaceMap& outputSurfaces);
/**
* Returns the maximum expected time it'll take for all currently in-flight
* requests to complete, based on their settings
*/
nsecs_t getExpectedInFlightDuration();
/**
* Tracking for idle detection
*/

Loading…
Cancel
Save