Camera: BufferManager: Don't attach/detach on every frame
- Maintain separate count of attached buffers
- Only attach when new buffers need to be allocated
- Only detach when a buffer needs to be freed
- Fix missing notification initializations
- Remove warning that's always logged
Bug: 28695173
Change-Id: I38e997fa1e69c2b8743e43eed31a6a08a6f9cd7a
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index d2b98e6..d09951a 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -120,24 +120,35 @@
ANativeWindowBuffer* anb;
int fenceFd = -1;
+ bool gotBufferFromManager = false;
+
if (mUseBufferManager) {
sp<GraphicBuffer> gb;
res = mBufferManager->getBufferForStream(getId(), getStreamSetId(), &gb, &fenceFd);
- if (res != OK) {
+ if (res == OK) {
+ // Attach this buffer to the bufferQueue: the buffer will be in dequeue state after a
+ // successful return.
+ anb = gb.get();
+ res = mConsumer->attachBuffer(anb);
+ if (res != OK) {
+ ALOGE("%s: Stream %d: Can't attach the output buffer to this surface: %s (%d)",
+ __FUNCTION__, mId, strerror(-res), res);
+ return res;
+ }
+ gotBufferFromManager = true;
+ ALOGV("Stream %d: Attached new buffer", getId());
+ } else if (res == ALREADY_EXISTS) {
+ // Have sufficient free buffers already attached, can just
+ // dequeue from buffer queue
+ ALOGV("Stream %d: Reusing attached buffer", getId());
+ gotBufferFromManager = false;
+ } else if (res != OK) {
ALOGE("%s: Stream %d: Can't get next output buffer from buffer manager: %s (%d)",
__FUNCTION__, mId, strerror(-res), res);
return res;
}
- // Attach this buffer to the bufferQueue: the buffer will be in dequeue state after a
- // successful return.
- anb = gb.get();
- res = mConsumer->attachBuffer(anb);
- if (res != OK) {
- ALOGE("%s: Stream %d: Can't attach the output buffer to this surface: %s (%d)",
- __FUNCTION__, mId, strerror(-res), res);
- return res;
- }
- } else {
+ }
+ if (!gotBufferFromManager) {
/**
* Release the lock briefly to avoid deadlock for below scenario:
* Thread 1: StreamingProcessor::startStream -> Camera3Stream::isConfiguring().
@@ -433,10 +444,15 @@
* HAL3.2 devices may not support the dynamic buffer registeration.
*/
if (mBufferManager != 0 && mSetId > CAMERA3_STREAM_SET_ID_INVALID) {
+ uint32_t consumerUsage = 0;
+ getEndpointUsage(&consumerUsage);
StreamInfo streamInfo(
getId(), getStreamSetId(), getWidth(), getHeight(), getFormat(), getDataSpace(),
- camera3_stream::usage, mTotalBufferCount, /*isConfigured*/true);
- res = mBufferManager->registerStream(streamInfo);
+ camera3_stream::usage | consumerUsage, mTotalBufferCount,
+ /*isConfigured*/true);
+ wp<Camera3OutputStream> weakThis(this);
+ res = mBufferManager->registerStream(weakThis,
+ streamInfo);
if (res == OK) {
// Disable buffer allocation for this BufferQueue, buffer manager will take over
// the buffer allocation responsibility.
@@ -561,34 +577,49 @@
return;
}
+ ALOGV("Stream %d: Buffer released", stream->getId());
+ status_t res = stream->mBufferManager->onBufferReleased(
+ stream->getId(), stream->getStreamSetId());
+ if (res != OK) {
+ ALOGE("%s: signaling buffer release to buffer manager failed: %s (%d).", __FUNCTION__,
+ strerror(-res), res);
+ stream->mState = STATE_ERROR;
+ }
+}
+
+status_t Camera3OutputStream::detachBuffer(sp<GraphicBuffer>* buffer, int* fenceFd) {
+ Mutex::Autolock l(mLock);
+
+ ALOGV("Stream %d: detachBuffer", getId());
+ if (buffer == nullptr) {
+ return BAD_VALUE;
+ }
+
sp<Fence> fence;
- sp<GraphicBuffer> buffer;
- int fenceFd = -1;
- status_t res = stream->mConsumer->detachNextBuffer(&buffer, &fence);
+ status_t res = mConsumer->detachNextBuffer(buffer, &fence);
if (res == NO_MEMORY) {
// This may rarely happen, which indicates that the released buffer was freed by other
// call (e.g., attachBuffer, dequeueBuffer etc.) before reaching here. We should notify the
// buffer manager that this buffer has been freed. It's not fatal, but should be avoided,
// therefore log a warning.
- buffer = 0;
+ *buffer = 0;
ALOGW("%s: the released buffer has already been freed by the buffer queue!", __FUNCTION__);
} else if (res != OK) {
// Other errors are fatal.
ALOGE("%s: detach next buffer failed: %s (%d).", __FUNCTION__, strerror(-res), res);
- stream->mState = STATE_ERROR;
- return;
+ mState = STATE_ERROR;
+ return res;
}
- if (fence!= 0 && fence->isValid()) {
- fenceFd = fence->dup();
+ if (fenceFd != nullptr) {
+ if (fence!= 0 && fence->isValid()) {
+ *fenceFd = fence->dup();
+ } else {
+ *fenceFd = -1;
+ }
}
- res = stream->mBufferManager->returnBufferForStream(stream->getId(), stream->getStreamSetId(),
- buffer, fenceFd);
- if (res != OK) {
- ALOGE("%s: return buffer to buffer manager failed: %s (%d).", __FUNCTION__,
- strerror(-res), res);
- stream->mState = STATE_ERROR;
- }
+
+ return OK;
}
bool Camera3OutputStream::isConsumedByHWComposer() const {