Camera: clear buffer cache when stream is reconfigured

Also fix a issue for finishConfiguration is unintentionally
delayed till first capture request.

Test: Camera CTS + partner device testing
Bug: 126390310
Change-Id: Ibca740a7160cbf41e01884dbcef8ba51eb4c75f7
gugelfrei
Yin-Chia Yeh 5 years ago
parent e069424fbe
commit 573a270f26

@ -2522,6 +2522,9 @@ status_t Camera3Device::setConsumerSurfaces(int streamId,
CLOGE("Stream %d is unknown", streamId); CLOGE("Stream %d is unknown", streamId);
return BAD_VALUE; return BAD_VALUE;
} }
// isConsumerConfigurationDeferred will be off after setConsumers
bool isDeferred = stream->isConsumerConfigurationDeferred();
status_t res = stream->setConsumers(consumers); status_t res = stream->setConsumers(consumers);
if (res != OK) { if (res != OK) {
CLOGE("Stream %d set consumer failed (error %d %s) ", streamId, res, strerror(-res)); CLOGE("Stream %d set consumer failed (error %d %s) ", streamId, res, strerror(-res));
@ -2537,7 +2540,7 @@ status_t Camera3Device::setConsumerSurfaces(int streamId,
surfaceIds->push_back(id); surfaceIds->push_back(id);
} }
if (stream->isConsumerConfigurationDeferred()) { if (isDeferred) {
if (!stream->isConfiguring()) { if (!stream->isConfiguring()) {
CLOGE("Stream %d was already fully configured.", streamId); CLOGE("Stream %d was already fully configured.", streamId);
return INVALID_OPERATION; return INVALID_OPERATION;
@ -2612,7 +2615,6 @@ status_t Camera3Device::dropStreamBuffers(bool dropping, int streamId) {
sp<Camera3Device::CaptureRequest> Camera3Device::createCaptureRequest( sp<Camera3Device::CaptureRequest> Camera3Device::createCaptureRequest(
const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) { const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
ATRACE_CALL(); ATRACE_CALL();
status_t res;
sp<CaptureRequest> newRequest = new CaptureRequest; sp<CaptureRequest> newRequest = new CaptureRequest;
newRequest->mSettingsList = request; newRequest->mSettingsList = request;
@ -2626,16 +2628,11 @@ sp<Camera3Device::CaptureRequest> Camera3Device::createCaptureRequest(
inputStreams.data.u8[0]); inputStreams.data.u8[0]);
return NULL; return NULL;
} }
// Lazy completion of stream configuration (allocation/registration)
// on first use
if (mInputStream->isConfiguring()) { if (mInputStream->isConfiguring()) {
res = mInputStream->finishConfiguration(); SET_ERR_L("%s: input stream %d is not configured!",
if (res != OK) { __FUNCTION__, mInputStream->getId());
SET_ERR_L("Unable to finish configuring input stream %d:" return NULL;
" %s (%d)",
mInputStream->getId(), strerror(-res), res);
return NULL;
}
} }
// Check if stream prepare is blocking requests. // Check if stream prepare is blocking requests.
if (mInputStream->isBlockedByPrepare()) { if (mInputStream->isBlockedByPrepare()) {
@ -2675,15 +2672,9 @@ sp<Camera3Device::CaptureRequest> Camera3Device::createCaptureRequest(
newRequest->mOutputSurfaces[streams.data.i32[i]] = surfaces; newRequest->mOutputSurfaces[streams.data.i32[i]] = surfaces;
} }
// Lazy completion of stream configuration (allocation/registration)
// on first use
if (stream->isConfiguring()) { if (stream->isConfiguring()) {
res = stream->finishConfiguration(); SET_ERR_L("%s: stream %d is not configured!", __FUNCTION__, stream->getId());
if (res != OK) { return NULL;
SET_ERR_L("Unable to finish configuring stream %d: %s (%d)",
stream->getId(), strerror(-res), res);
return NULL;
}
} }
// Check if stream prepare is blocking requests. // Check if stream prepare is blocking requests.
if (stream->isBlockedByPrepare()) { if (stream->isBlockedByPrepare()) {
@ -2908,7 +2899,8 @@ status_t Camera3Device::configureStreamsLocked(int operatingMode,
// faster // faster
if (mInputStream != NULL && mInputStream->isConfiguring()) { if (mInputStream != NULL && mInputStream->isConfiguring()) {
res = mInputStream->finishConfiguration(); bool streamReConfigured = false;
res = mInputStream->finishConfiguration(&streamReConfigured);
if (res != OK) { if (res != OK) {
CLOGE("Can't finish configuring input stream %d: %s (%d)", CLOGE("Can't finish configuring input stream %d: %s (%d)",
mInputStream->getId(), strerror(-res), res); mInputStream->getId(), strerror(-res), res);
@ -2918,12 +2910,16 @@ status_t Camera3Device::configureStreamsLocked(int operatingMode,
} }
return BAD_VALUE; return BAD_VALUE;
} }
if (streamReConfigured) {
mInterface->onStreamReConfigured(mInputStream->getId());
}
} }
for (size_t i = 0; i < mOutputStreams.size(); i++) { for (size_t i = 0; i < mOutputStreams.size(); i++) {
sp<Camera3OutputStreamInterface> outputStream = mOutputStreams[i]; sp<Camera3OutputStreamInterface> outputStream = mOutputStreams[i];
if (outputStream->isConfiguring() && !outputStream->isConsumerConfigurationDeferred()) { if (outputStream->isConfiguring() && !outputStream->isConsumerConfigurationDeferred()) {
res = outputStream->finishConfiguration(); bool streamReConfigured = false;
res = outputStream->finishConfiguration(&streamReConfigured);
if (res != OK) { if (res != OK) {
CLOGE("Can't finish configuring output stream %d: %s (%d)", CLOGE("Can't finish configuring output stream %d: %s (%d)",
outputStream->getId(), strerror(-res), res); outputStream->getId(), strerror(-res), res);
@ -2933,6 +2929,9 @@ status_t Camera3Device::configureStreamsLocked(int operatingMode,
} }
return BAD_VALUE; return BAD_VALUE;
} }
if (streamReConfigured) {
mInterface->onStreamReConfigured(outputStream->getId());
}
} }
} }
@ -4780,7 +4779,7 @@ void Camera3Device::HalInterface::onBufferFreed(
__FUNCTION__, handle, streamId); __FUNCTION__, handle, streamId);
return; return;
} else { } else {
bufferId = it->second; bufferId = it->second;
bIdMap.erase(it); bIdMap.erase(it);
ALOGV("%s: stream %d now have %zu buffer caches after removing buf %p", ALOGV("%s: stream %d now have %zu buffer caches after removing buf %p",
__FUNCTION__, streamId, bIdMap.size(), handle); __FUNCTION__, streamId, bIdMap.size(), handle);
@ -4788,6 +4787,22 @@ void Camera3Device::HalInterface::onBufferFreed(
mFreedBuffers.push_back(std::make_pair(streamId, bufferId)); mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
} }
void Camera3Device::HalInterface::onStreamReConfigured(int streamId) {
std::lock_guard<std::mutex> lock(mBufferIdMapLock);
auto mapIt = mBufferIdMaps.find(streamId);
if (mapIt == mBufferIdMaps.end()) {
ALOGE("%s: streamId %d not found!", __FUNCTION__, streamId);
return;
}
BufferIdMap& bIdMap = mapIt->second;
for (const auto& it : bIdMap) {
uint64_t bufferId = it.second;
mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
}
bIdMap.clear();
}
/** /**
* RequestThread inner class methods * RequestThread inner class methods
*/ */

@ -336,6 +336,8 @@ class Camera3Device :
// Get a vector of bufferId of currently inflight buffers // Get a vector of bufferId of currently inflight buffers
void getInflightRequestBufferKeys(std::vector<uint64_t>* out); void getInflightRequestBufferKeys(std::vector<uint64_t>* out);
void onStreamReConfigured(int streamId);
static const uint64_t BUFFER_ID_NO_BUFFER = 0; static const uint64_t BUFFER_ID_NO_BUFFER = 0;
private: private:
// Always valid // Always valid

@ -287,8 +287,11 @@ bool Camera3Stream::isConfiguring() const {
return (mState == STATE_IN_CONFIG) || (mState == STATE_IN_RECONFIG); return (mState == STATE_IN_CONFIG) || (mState == STATE_IN_RECONFIG);
} }
status_t Camera3Stream::finishConfiguration() { status_t Camera3Stream::finishConfiguration(/*out*/bool* streamReconfigured) {
ATRACE_CALL(); ATRACE_CALL();
if (streamReconfigured != nullptr) {
*streamReconfigured = false;
}
Mutex::Autolock l(mLock); Mutex::Autolock l(mLock);
switch (mState) { switch (mState) {
case STATE_ERROR: case STATE_ERROR:
@ -313,7 +316,7 @@ status_t Camera3Stream::finishConfiguration() {
// Register for idle tracking // Register for idle tracking
sp<StatusTracker> statusTracker = mStatusTracker.promote(); sp<StatusTracker> statusTracker = mStatusTracker.promote();
if (statusTracker != 0) { if (statusTracker != 0 && mStatusId == StatusTracker::NO_STATUS_ID) {
mStatusId = statusTracker->addComponent(); mStatusId = statusTracker->addComponent();
} }
@ -332,6 +335,7 @@ status_t Camera3Stream::finishConfiguration() {
mPrepareBlockRequest = true; mPrepareBlockRequest = true;
mStreamUnpreparable = false; mStreamUnpreparable = false;
bool reconfiguring = (mState == STATE_IN_RECONFIG);
status_t res; status_t res;
res = configureQueueLocked(); res = configureQueueLocked();
// configureQueueLocked could return error in case of abandoned surface. // configureQueueLocked could return error in case of abandoned surface.
@ -348,6 +352,9 @@ status_t Camera3Stream::finishConfiguration() {
return res; return res;
} }
if (reconfiguring && streamReconfigured != nullptr) {
*streamReconfigured = true;
}
mState = STATE_CONFIGURED; mState = STATE_CONFIGURED;
return res; return res;

@ -197,6 +197,8 @@ class Camera3Stream :
* after this call, but can still be read until the destruction of the * after this call, but can still be read until the destruction of the
* stream. * stream.
* *
* streamReconfigured: set to true when a stream is being reconfigured.
*
* Returns: * Returns:
* OK on a successful configuration * OK on a successful configuration
* NO_INIT in case of a serious error from the HAL device * NO_INIT in case of a serious error from the HAL device
@ -204,7 +206,7 @@ class Camera3Stream :
* INVALID_OPERATION in case connecting to the consumer failed or consumer * INVALID_OPERATION in case connecting to the consumer failed or consumer
* doesn't exist yet. * doesn't exist yet.
*/ */
status_t finishConfiguration(); status_t finishConfiguration(/*out*/bool* streamReconfigured = nullptr);
/** /**
* Cancels the stream configuration process. This returns the stream to the * Cancels the stream configuration process. This returns the stream to the

@ -130,13 +130,15 @@ class Camera3StreamInterface : public virtual RefBase {
* modified after this call, but can still be read until the destruction of * modified after this call, but can still be read until the destruction of
* the stream. * the stream.
* *
* streamReconfigured: set to true when a stream is being reconfigured.
*
* Returns: * Returns:
* OK on a successful configuration * OK on a successful configuration
* NO_INIT in case of a serious error from the HAL device * NO_INIT in case of a serious error from the HAL device
* NO_MEMORY in case of an error registering buffers * NO_MEMORY in case of an error registering buffers
* INVALID_OPERATION in case connecting to the consumer failed * INVALID_OPERATION in case connecting to the consumer failed
*/ */
virtual status_t finishConfiguration() = 0; virtual status_t finishConfiguration(/*out*/bool* streamReconfigured = nullptr) = 0;
/** /**
* Cancels the stream configuration process. This returns the stream to the * Cancels the stream configuration process. This returns the stream to the

Loading…
Cancel
Save