Loading services/camera/libcameraservice/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ LOCAL_SRC_FILES:= \ camera2/ProFrameProcessor.cpp \ camera2/ZslProcessor3.cpp \ camera3/Camera3Stream.cpp \ camera3/Camera3IOStreamBase.cpp \ camera3/Camera3InputStream.cpp \ camera3/Camera3OutputStream.cpp \ camera3/Camera3ZslStream.cpp \ Loading services/camera/libcameraservice/camera3/Camera3IOStreamBase.cpp 0 → 100644 +273 −0 Original line number Diff line number Diff line /* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "Camera3-IOStreamBase" #define ATRACE_TAG ATRACE_TAG_CAMERA //#define LOG_NDEBUG 0 // This is needed for stdint.h to define INT64_MAX in C++ #define __STDC_LIMIT_MACROS #include <utils/Log.h> #include <utils/Trace.h> #include "Camera3IOStreamBase.h" namespace android { namespace camera3 { Camera3IOStreamBase::Camera3IOStreamBase(int id, camera3_stream_type_t type, uint32_t width, uint32_t height, size_t maxSize, int format) : Camera3Stream(id, type, width, height, maxSize, format), mTotalBufferCount(0), mDequeuedBufferCount(0), mFrameCount(0), mLastTimestamp(0) { mCombinedFence = new Fence(); if (maxSize > 0 && format != HAL_PIXEL_FORMAT_BLOB) { ALOGE("%s: Bad format for size-only stream: %d", __FUNCTION__, format); mState = STATE_ERROR; } } Camera3IOStreamBase::~Camera3IOStreamBase() { disconnectLocked(); } bool Camera3IOStreamBase::hasOutstandingBuffersLocked() const { nsecs_t signalTime = mCombinedFence->getSignalTime(); ALOGV("%s: Stream %d: Has %d outstanding buffers," " buffer signal time is %lld", __FUNCTION__, mId, mDequeuedBufferCount, signalTime); if (mDequeuedBufferCount > 0 || signalTime == INT64_MAX) { return true; } return false; } status_t Camera3IOStreamBase::waitUntilIdle(nsecs_t timeout) { status_t res; { Mutex::Autolock l(mLock); while (mDequeuedBufferCount > 0) { if (timeout != TIMEOUT_NEVER) { nsecs_t startTime = systemTime(); res = mBufferReturnedSignal.waitRelative(mLock, timeout); if (res == TIMED_OUT) { return res; } else if (res != OK) { ALOGE("%s: Error waiting for outstanding buffers: %s (%d)", __FUNCTION__, strerror(-res), res); return res; } nsecs_t deltaTime = systemTime() - startTime; if (timeout <= deltaTime) { timeout = 0; } else { timeout -= deltaTime; } } else { res = mBufferReturnedSignal.wait(mLock); if (res != OK) { ALOGE("%s: Error waiting for outstanding buffers: %s (%d)", __FUNCTION__, strerror(-res), res); return res; } } } } // No lock unsigned int timeoutMs; if (timeout == TIMEOUT_NEVER) { timeoutMs = Fence::TIMEOUT_NEVER; } else if (timeout == 0) { timeoutMs = 0; } else { // Round up to wait at least 1 ms timeoutMs = (timeout + 999999) / 1000000; } return mCombinedFence->wait(timeoutMs); } void Camera3IOStreamBase::dump(int fd, const Vector<String16> &args) const { (void) args; String8 lines; lines.appendFormat(" State: %d\n", mState); lines.appendFormat(" Dims: %d x %d, format 0x%x\n", camera3_stream::width, camera3_stream::height, camera3_stream::format); lines.appendFormat(" Max size: %d\n", mMaxSize); lines.appendFormat(" Usage: %d, max HAL buffers: %d\n", camera3_stream::usage, camera3_stream::max_buffers); lines.appendFormat(" Frames produced: %d, last timestamp: %lld ns\n", mFrameCount, mLastTimestamp); lines.appendFormat(" Total buffers: %d, currently dequeued: %d\n", mTotalBufferCount, mDequeuedBufferCount); write(fd, lines.string(), lines.size()); } status_t Camera3IOStreamBase::configureQueueLocked() { status_t res; switch (mState) { case STATE_IN_RECONFIG: res = disconnectLocked(); if (res != OK) { return res; } break; case STATE_IN_CONFIG: // OK break; default: ALOGE("%s: Bad state: %d", __FUNCTION__, mState); return INVALID_OPERATION; } return OK; } size_t Camera3IOStreamBase::getBufferCountLocked() { return mTotalBufferCount; } status_t Camera3IOStreamBase::disconnectLocked() { switch (mState) { case STATE_IN_RECONFIG: case STATE_CONFIGURED: // OK break; default: // No connection, nothing to do return OK; } if (mDequeuedBufferCount > 0) { ALOGE("%s: Can't disconnect with %d buffers still dequeued!", __FUNCTION__, mDequeuedBufferCount); return INVALID_OPERATION; } return OK; } void Camera3IOStreamBase::handoutBufferLocked(camera3_stream_buffer &buffer, buffer_handle_t *handle, int acquireFence, int releaseFence, camera3_buffer_status_t status) { /** * Note that all fences are now owned by HAL. */ // Handing out a raw pointer to this object. Increment internal refcount. incStrong(this); buffer.stream = this; buffer.buffer = handle; buffer.acquire_fence = acquireFence; buffer.release_fence = releaseFence; buffer.status = status; mDequeuedBufferCount++; } status_t Camera3IOStreamBase::getBufferPreconditionCheckLocked() const { // Allow dequeue during IN_[RE]CONFIG for registration if (mState != STATE_CONFIGURED && mState != STATE_IN_CONFIG && mState != STATE_IN_RECONFIG) { ALOGE("%s: Stream %d: Can't get buffers in unconfigured state %d", __FUNCTION__, mId, mState); return INVALID_OPERATION; } // Only limit dequeue amount when fully configured if (mState == STATE_CONFIGURED && mDequeuedBufferCount == camera3_stream::max_buffers) { ALOGE("%s: Stream %d: Already dequeued maximum number of simultaneous" " buffers (%d)", __FUNCTION__, mId, camera3_stream::max_buffers); return INVALID_OPERATION; } return OK; } status_t Camera3IOStreamBase::returnBufferPreconditionCheckLocked() const { // Allow buffers to be returned in the error state, to allow for disconnect // and in the in-config states for registration if (mState == STATE_CONSTRUCTED) { ALOGE("%s: Stream %d: Can't return buffers in unconfigured state %d", __FUNCTION__, mId, mState); return INVALID_OPERATION; } if (mDequeuedBufferCount == 0) { ALOGE("%s: Stream %d: No buffers outstanding to return", __FUNCTION__, mId); return INVALID_OPERATION; } return OK; } status_t Camera3IOStreamBase::returnAnyBufferLocked( const camera3_stream_buffer &buffer, nsecs_t timestamp, bool output) { status_t res; // returnBuffer may be called from a raw pointer, not a sp<>, and we'll be // decrementing the internal refcount next. In case this is the last ref, we // might get destructed on the decStrong(), so keep an sp around until the // end of the call - otherwise have to sprinkle the decStrong on all exit // points. sp<Camera3IOStreamBase> keepAlive(this); decStrong(this); if ((res = returnBufferPreconditionCheckLocked()) != OK) { return res; } sp<Fence> releaseFence; res = returnBufferCheckedLocked(buffer, timestamp, output, &releaseFence); if (res != OK) { return res; } mCombinedFence = Fence::merge(mName, mCombinedFence, releaseFence); mDequeuedBufferCount--; mBufferReturnedSignal.signal(); if (output) { mLastTimestamp = timestamp; } return OK; } }; // namespace camera3 }; // namespace android services/camera/libcameraservice/camera3/Camera3IOStreamBase.h 0 → 100644 +102 −0 Original line number Diff line number Diff line /* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_SERVERS_CAMERA3_IO_STREAM_BASE_H #define ANDROID_SERVERS_CAMERA3_IO_STREAM_BASE_H #include <utils/RefBase.h> #include <gui/Surface.h> #include "Camera3Stream.h" namespace android { namespace camera3 { /** * A base class for managing a single stream of I/O data from the camera device. */ class Camera3IOStreamBase : public Camera3Stream { protected: Camera3IOStreamBase(int id, camera3_stream_type_t type, uint32_t width, uint32_t height, size_t maxSize, int format); public: virtual ~Camera3IOStreamBase(); /** * Camera3Stream interface */ virtual status_t waitUntilIdle(nsecs_t timeout); virtual void dump(int fd, const Vector<String16> &args) const; protected: size_t mTotalBufferCount; // sum of input and output buffers that are currently acquired by HAL size_t mDequeuedBufferCount; Condition mBufferReturnedSignal; uint32_t mFrameCount; // Last received output buffer's timestamp nsecs_t mLastTimestamp; // The merged release fence for all returned buffers sp<Fence> mCombinedFence; status_t returnAnyBufferLocked( const camera3_stream_buffer &buffer, nsecs_t timestamp, bool output); virtual status_t returnBufferCheckedLocked( const camera3_stream_buffer &buffer, nsecs_t timestamp, bool output, /*out*/ sp<Fence> *releaseFenceOut) = 0; /** * Internal Camera3Stream interface */ virtual bool hasOutstandingBuffersLocked() const; virtual size_t getBufferCountLocked(); status_t getBufferPreconditionCheckLocked() const; status_t returnBufferPreconditionCheckLocked() const; // State check only virtual status_t configureQueueLocked(); // State checks only virtual status_t disconnectLocked(); // Hand out the buffer to a native location, // incrementing the internal refcount and dequeued buffer count void handoutBufferLocked(camera3_stream_buffer &buffer, buffer_handle_t *handle, int acquire_fence, int release_fence, camera3_buffer_status_t status); }; // class Camera3IOStreamBase } // namespace camera3 } // namespace android #endif services/camera/libcameraservice/camera3/Camera3InputStream.cpp +33 −160 Original line number Diff line number Diff line Loading @@ -18,9 +18,6 @@ #define ATRACE_TAG ATRACE_TAG_CAMERA //#define LOG_NDEBUG 0 // This is needed for stdint.h to define INT64_MAX in C++ #define __STDC_LIMIT_MACROS #include <utils/Log.h> #include <utils/Trace.h> #include "Camera3InputStream.h" Loading @@ -31,12 +28,8 @@ namespace camera3 { Camera3InputStream::Camera3InputStream(int id, uint32_t width, uint32_t height, int format) : Camera3Stream(id, CAMERA3_STREAM_INPUT, width, height, 0, format), mTotalBufferCount(0), mDequeuedBufferCount(0), mFrameCount(0), mLastTimestamp(0) { mCombinedFence = new Fence(); Camera3IOStreamBase(id, CAMERA3_STREAM_INPUT, width, height, /*maxSize*/0, format) { if (format == HAL_PIXEL_FORMAT_BLOB) { ALOGE("%s: Bad format, BLOB not supported", __FUNCTION__); Loading @@ -61,21 +54,8 @@ status_t Camera3InputStream::getInputBufferLocked( return INVALID_OPERATION; } // Allow acquire during IN_[RE]CONFIG for registration if (mState != STATE_CONFIGURED && mState != STATE_IN_CONFIG && mState != STATE_IN_RECONFIG) { ALOGE("%s: Stream %d: Can't get buffers in unconfigured state %d", __FUNCTION__, mId, mState); return INVALID_OPERATION; } // Only limit acquire amount when fully configured if (mState == STATE_CONFIGURED && mDequeuedBufferCount == camera3_stream::max_buffers) { ALOGE("%s: Stream %d: Already acquired maximum number of simultaneous" " buffers (%d)", __FUNCTION__, mId, camera3_stream::max_buffers); return INVALID_OPERATION; if ((res = getBufferPreconditionCheckLocked()) != OK) { return res; } ANativeWindowBuffer* anb; Loading @@ -95,51 +75,30 @@ status_t Camera3InputStream::getInputBufferLocked( anb = bufferItem.mGraphicBuffer->getNativeBuffer(); assert(anb != NULL); fenceFd = bufferItem.mFence->dup(); /** * FenceFD now owned by HAL except in case of error, * in which case we reassign it to acquire_fence */ // Handing out a raw pointer to this object. Increment internal refcount. incStrong(this); buffer->stream = this; buffer->buffer = &(anb->handle); buffer->acquire_fence = fenceFd; buffer->release_fence = -1; buffer->status = CAMERA3_BUFFER_STATUS_OK; mDequeuedBufferCount++; handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd, /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK); mBuffersInFlight.push_back(bufferItem); return OK; } status_t Camera3InputStream::returnInputBufferLocked( const camera3_stream_buffer &buffer) { ATRACE_CALL(); status_t res; status_t Camera3InputStream::returnBufferCheckedLocked( const camera3_stream_buffer &buffer, nsecs_t timestamp, bool output, /*out*/ sp<Fence> *releaseFenceOut) { // returnBuffer may be called from a raw pointer, not a sp<>, and we'll be // decrementing the internal refcount next. In case this is the last ref, we // might get destructed on the decStrong(), so keep an sp around until the // end of the call - otherwise have to sprinkle the decStrong on all exit // points. sp<Camera3InputStream> keepAlive(this); decStrong(this); // Allow buffers to be returned in the error state, to allow for disconnect // and in the in-config states for registration if (mState == STATE_CONSTRUCTED) { ALOGE("%s: Stream %d: Can't return buffers in unconfigured state %d", __FUNCTION__, mId, mState); return INVALID_OPERATION; } if (mDequeuedBufferCount == 0) { ALOGE("%s: Stream %d: No buffers outstanding to return", __FUNCTION__, mId); return INVALID_OPERATION; } (void)timestamp; (void)output; ALOG_ASSERT(!output, "Expected output to be false"); status_t res; bool bufferFound = false; BufferItem bufferItem; Loading Loading @@ -192,91 +151,24 @@ status_t Camera3InputStream::returnInputBufferLocked( return res; } mCombinedFence = Fence::merge(mName, mCombinedFence, releaseFence); mBufferReturnedSignal.signal(); *releaseFenceOut = releaseFence; return OK; } bool Camera3InputStream::hasOutstandingBuffersLocked() const { nsecs_t signalTime = mCombinedFence->getSignalTime(); ALOGV("%s: Stream %d: Has %d outstanding buffers," " buffer signal time is %lld", __FUNCTION__, mId, mDequeuedBufferCount, signalTime); if (mDequeuedBufferCount > 0 || signalTime == INT64_MAX) { return true; } return false; } status_t Camera3InputStream::waitUntilIdle(nsecs_t timeout) { status_t res; { Mutex::Autolock l(mLock); while (mDequeuedBufferCount > 0) { if (timeout != TIMEOUT_NEVER) { nsecs_t startTime = systemTime(); res = mBufferReturnedSignal.waitRelative(mLock, timeout); if (res == TIMED_OUT) { return res; } else if (res != OK) { ALOGE("%s: Error waiting for outstanding buffers: %s (%d)", __FUNCTION__, strerror(-res), res); return res; } nsecs_t deltaTime = systemTime() - startTime; if (timeout <= deltaTime) { timeout = 0; } else { timeout -= deltaTime; } } else { res = mBufferReturnedSignal.wait(mLock); if (res != OK) { ALOGE("%s: Error waiting for outstanding buffers: %s (%d)", __FUNCTION__, strerror(-res), res); return res; } } } } // No lock unsigned int timeoutMs; if (timeout == TIMEOUT_NEVER) { timeoutMs = Fence::TIMEOUT_NEVER; } else if (timeout == 0) { timeoutMs = 0; } else { // Round up to wait at least 1 ms timeoutMs = (timeout + 999999) / 1000000; } return mCombinedFence->wait(timeoutMs); } status_t Camera3InputStream::returnInputBufferLocked( const camera3_stream_buffer &buffer) { ATRACE_CALL(); size_t Camera3InputStream::getBufferCountLocked() { return mTotalBufferCount; return returnAnyBufferLocked(buffer, /*timestamp*/0, /*output*/false); } status_t Camera3InputStream::disconnectLocked() { switch (mState) { case STATE_IN_RECONFIG: case STATE_CONFIGURED: // OK break; default: // No connection, nothing to do return OK; } if (mDequeuedBufferCount > 0) { ALOGE("%s: Can't disconnect with %d buffers still acquired!", __FUNCTION__, mDequeuedBufferCount); return INVALID_OPERATION; status_t res; if ((res = Camera3IOStreamBase::disconnectLocked()) != OK) { return res; } assert(mBuffersInFlight.size() == 0); Loading @@ -285,7 +177,8 @@ status_t Camera3InputStream::disconnectLocked() { * no-op since we can't disconnect the producer from the consumer-side */ mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG : STATE_CONSTRUCTED; mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG : STATE_CONSTRUCTED; return OK; } Loading @@ -297,37 +190,17 @@ void Camera3InputStream::dump(int fd, const Vector<String16> &args) const { (void) args; String8 lines; lines.appendFormat(" Stream[%d]: Input\n", mId); lines.appendFormat(" State: %d\n", mState); lines.appendFormat(" Dims: %d x %d, format 0x%x\n", camera3_stream::width, camera3_stream::height, camera3_stream::format); lines.appendFormat(" Max size: %d\n", mMaxSize); lines.appendFormat(" Usage: %d, max HAL buffers: %d\n", camera3_stream::usage, camera3_stream::max_buffers); lines.appendFormat(" Frames produced: %d, last timestamp: %lld ns\n", mFrameCount, mLastTimestamp); lines.appendFormat(" Total buffers: %d, currently acquired: %d\n", mTotalBufferCount, mDequeuedBufferCount); write(fd, lines.string(), lines.size()); Camera3IOStreamBase::dump(fd, args); } status_t Camera3InputStream::configureQueueLocked() { status_t res; switch (mState) { case STATE_IN_RECONFIG: res = disconnectLocked(); if (res != OK) { if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) { return res; } break; case STATE_IN_CONFIG: // OK break; default: ALOGE("%s: Bad state: %d", __FUNCTION__, mState); return INVALID_OPERATION; } assert(mMaxSize == 0); assert(camera3_stream::format != HAL_PIXEL_FORMAT_BLOB); Loading services/camera/libcameraservice/camera3/Camera3InputStream.h +11 −12 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ #include <gui/Surface.h> #include <gui/BufferItemConsumer.h> #include "Camera3Stream.h" #include "Camera3IOStreamBase.h" namespace android { Loading @@ -34,7 +34,7 @@ namespace camera3 { * buffers by feeding them into the HAL, as well as releasing the buffers back * the buffers once the HAL is done with them. */ class Camera3InputStream : public Camera3Stream { class Camera3InputStream : public Camera3IOStreamBase { public: /** * Set up a stream for formats that have fixed size, such as RAW and YUV. Loading @@ -42,7 +42,6 @@ class Camera3InputStream : public Camera3Stream { Camera3InputStream(int id, uint32_t width, uint32_t height, int format); ~Camera3InputStream(); virtual status_t waitUntilIdle(nsecs_t timeout); virtual void dump(int fd, const Vector<String16> &args) const; /** Loading @@ -58,14 +57,16 @@ class Camera3InputStream : public Camera3Stream { sp<BufferItemConsumer> mConsumer; Vector<BufferItem> mBuffersInFlight; size_t mTotalBufferCount; size_t mDequeuedBufferCount; Condition mBufferReturnedSignal; uint32_t mFrameCount; nsecs_t mLastTimestamp; // The merged release fence for all returned buffers sp<Fence> mCombinedFence; /** * Camera3IOStreamBase */ virtual status_t returnBufferCheckedLocked( const camera3_stream_buffer &buffer, nsecs_t timestamp, bool output, /*out*/ sp<Fence> *releaseFenceOut); /** * Camera3Stream interface Loading @@ -74,11 +75,9 @@ class Camera3InputStream : public Camera3Stream { virtual status_t getInputBufferLocked(camera3_stream_buffer *buffer); virtual status_t returnInputBufferLocked( const camera3_stream_buffer &buffer); virtual bool hasOutstandingBuffersLocked() const; virtual status_t disconnectLocked(); virtual status_t configureQueueLocked(); virtual size_t getBufferCountLocked(); }; // class Camera3InputStream Loading Loading
services/camera/libcameraservice/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ LOCAL_SRC_FILES:= \ camera2/ProFrameProcessor.cpp \ camera2/ZslProcessor3.cpp \ camera3/Camera3Stream.cpp \ camera3/Camera3IOStreamBase.cpp \ camera3/Camera3InputStream.cpp \ camera3/Camera3OutputStream.cpp \ camera3/Camera3ZslStream.cpp \ Loading
services/camera/libcameraservice/camera3/Camera3IOStreamBase.cpp 0 → 100644 +273 −0 Original line number Diff line number Diff line /* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "Camera3-IOStreamBase" #define ATRACE_TAG ATRACE_TAG_CAMERA //#define LOG_NDEBUG 0 // This is needed for stdint.h to define INT64_MAX in C++ #define __STDC_LIMIT_MACROS #include <utils/Log.h> #include <utils/Trace.h> #include "Camera3IOStreamBase.h" namespace android { namespace camera3 { Camera3IOStreamBase::Camera3IOStreamBase(int id, camera3_stream_type_t type, uint32_t width, uint32_t height, size_t maxSize, int format) : Camera3Stream(id, type, width, height, maxSize, format), mTotalBufferCount(0), mDequeuedBufferCount(0), mFrameCount(0), mLastTimestamp(0) { mCombinedFence = new Fence(); if (maxSize > 0 && format != HAL_PIXEL_FORMAT_BLOB) { ALOGE("%s: Bad format for size-only stream: %d", __FUNCTION__, format); mState = STATE_ERROR; } } Camera3IOStreamBase::~Camera3IOStreamBase() { disconnectLocked(); } bool Camera3IOStreamBase::hasOutstandingBuffersLocked() const { nsecs_t signalTime = mCombinedFence->getSignalTime(); ALOGV("%s: Stream %d: Has %d outstanding buffers," " buffer signal time is %lld", __FUNCTION__, mId, mDequeuedBufferCount, signalTime); if (mDequeuedBufferCount > 0 || signalTime == INT64_MAX) { return true; } return false; } status_t Camera3IOStreamBase::waitUntilIdle(nsecs_t timeout) { status_t res; { Mutex::Autolock l(mLock); while (mDequeuedBufferCount > 0) { if (timeout != TIMEOUT_NEVER) { nsecs_t startTime = systemTime(); res = mBufferReturnedSignal.waitRelative(mLock, timeout); if (res == TIMED_OUT) { return res; } else if (res != OK) { ALOGE("%s: Error waiting for outstanding buffers: %s (%d)", __FUNCTION__, strerror(-res), res); return res; } nsecs_t deltaTime = systemTime() - startTime; if (timeout <= deltaTime) { timeout = 0; } else { timeout -= deltaTime; } } else { res = mBufferReturnedSignal.wait(mLock); if (res != OK) { ALOGE("%s: Error waiting for outstanding buffers: %s (%d)", __FUNCTION__, strerror(-res), res); return res; } } } } // No lock unsigned int timeoutMs; if (timeout == TIMEOUT_NEVER) { timeoutMs = Fence::TIMEOUT_NEVER; } else if (timeout == 0) { timeoutMs = 0; } else { // Round up to wait at least 1 ms timeoutMs = (timeout + 999999) / 1000000; } return mCombinedFence->wait(timeoutMs); } void Camera3IOStreamBase::dump(int fd, const Vector<String16> &args) const { (void) args; String8 lines; lines.appendFormat(" State: %d\n", mState); lines.appendFormat(" Dims: %d x %d, format 0x%x\n", camera3_stream::width, camera3_stream::height, camera3_stream::format); lines.appendFormat(" Max size: %d\n", mMaxSize); lines.appendFormat(" Usage: %d, max HAL buffers: %d\n", camera3_stream::usage, camera3_stream::max_buffers); lines.appendFormat(" Frames produced: %d, last timestamp: %lld ns\n", mFrameCount, mLastTimestamp); lines.appendFormat(" Total buffers: %d, currently dequeued: %d\n", mTotalBufferCount, mDequeuedBufferCount); write(fd, lines.string(), lines.size()); } status_t Camera3IOStreamBase::configureQueueLocked() { status_t res; switch (mState) { case STATE_IN_RECONFIG: res = disconnectLocked(); if (res != OK) { return res; } break; case STATE_IN_CONFIG: // OK break; default: ALOGE("%s: Bad state: %d", __FUNCTION__, mState); return INVALID_OPERATION; } return OK; } size_t Camera3IOStreamBase::getBufferCountLocked() { return mTotalBufferCount; } status_t Camera3IOStreamBase::disconnectLocked() { switch (mState) { case STATE_IN_RECONFIG: case STATE_CONFIGURED: // OK break; default: // No connection, nothing to do return OK; } if (mDequeuedBufferCount > 0) { ALOGE("%s: Can't disconnect with %d buffers still dequeued!", __FUNCTION__, mDequeuedBufferCount); return INVALID_OPERATION; } return OK; } void Camera3IOStreamBase::handoutBufferLocked(camera3_stream_buffer &buffer, buffer_handle_t *handle, int acquireFence, int releaseFence, camera3_buffer_status_t status) { /** * Note that all fences are now owned by HAL. */ // Handing out a raw pointer to this object. Increment internal refcount. incStrong(this); buffer.stream = this; buffer.buffer = handle; buffer.acquire_fence = acquireFence; buffer.release_fence = releaseFence; buffer.status = status; mDequeuedBufferCount++; } status_t Camera3IOStreamBase::getBufferPreconditionCheckLocked() const { // Allow dequeue during IN_[RE]CONFIG for registration if (mState != STATE_CONFIGURED && mState != STATE_IN_CONFIG && mState != STATE_IN_RECONFIG) { ALOGE("%s: Stream %d: Can't get buffers in unconfigured state %d", __FUNCTION__, mId, mState); return INVALID_OPERATION; } // Only limit dequeue amount when fully configured if (mState == STATE_CONFIGURED && mDequeuedBufferCount == camera3_stream::max_buffers) { ALOGE("%s: Stream %d: Already dequeued maximum number of simultaneous" " buffers (%d)", __FUNCTION__, mId, camera3_stream::max_buffers); return INVALID_OPERATION; } return OK; } status_t Camera3IOStreamBase::returnBufferPreconditionCheckLocked() const { // Allow buffers to be returned in the error state, to allow for disconnect // and in the in-config states for registration if (mState == STATE_CONSTRUCTED) { ALOGE("%s: Stream %d: Can't return buffers in unconfigured state %d", __FUNCTION__, mId, mState); return INVALID_OPERATION; } if (mDequeuedBufferCount == 0) { ALOGE("%s: Stream %d: No buffers outstanding to return", __FUNCTION__, mId); return INVALID_OPERATION; } return OK; } status_t Camera3IOStreamBase::returnAnyBufferLocked( const camera3_stream_buffer &buffer, nsecs_t timestamp, bool output) { status_t res; // returnBuffer may be called from a raw pointer, not a sp<>, and we'll be // decrementing the internal refcount next. In case this is the last ref, we // might get destructed on the decStrong(), so keep an sp around until the // end of the call - otherwise have to sprinkle the decStrong on all exit // points. sp<Camera3IOStreamBase> keepAlive(this); decStrong(this); if ((res = returnBufferPreconditionCheckLocked()) != OK) { return res; } sp<Fence> releaseFence; res = returnBufferCheckedLocked(buffer, timestamp, output, &releaseFence); if (res != OK) { return res; } mCombinedFence = Fence::merge(mName, mCombinedFence, releaseFence); mDequeuedBufferCount--; mBufferReturnedSignal.signal(); if (output) { mLastTimestamp = timestamp; } return OK; } }; // namespace camera3 }; // namespace android
services/camera/libcameraservice/camera3/Camera3IOStreamBase.h 0 → 100644 +102 −0 Original line number Diff line number Diff line /* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_SERVERS_CAMERA3_IO_STREAM_BASE_H #define ANDROID_SERVERS_CAMERA3_IO_STREAM_BASE_H #include <utils/RefBase.h> #include <gui/Surface.h> #include "Camera3Stream.h" namespace android { namespace camera3 { /** * A base class for managing a single stream of I/O data from the camera device. */ class Camera3IOStreamBase : public Camera3Stream { protected: Camera3IOStreamBase(int id, camera3_stream_type_t type, uint32_t width, uint32_t height, size_t maxSize, int format); public: virtual ~Camera3IOStreamBase(); /** * Camera3Stream interface */ virtual status_t waitUntilIdle(nsecs_t timeout); virtual void dump(int fd, const Vector<String16> &args) const; protected: size_t mTotalBufferCount; // sum of input and output buffers that are currently acquired by HAL size_t mDequeuedBufferCount; Condition mBufferReturnedSignal; uint32_t mFrameCount; // Last received output buffer's timestamp nsecs_t mLastTimestamp; // The merged release fence for all returned buffers sp<Fence> mCombinedFence; status_t returnAnyBufferLocked( const camera3_stream_buffer &buffer, nsecs_t timestamp, bool output); virtual status_t returnBufferCheckedLocked( const camera3_stream_buffer &buffer, nsecs_t timestamp, bool output, /*out*/ sp<Fence> *releaseFenceOut) = 0; /** * Internal Camera3Stream interface */ virtual bool hasOutstandingBuffersLocked() const; virtual size_t getBufferCountLocked(); status_t getBufferPreconditionCheckLocked() const; status_t returnBufferPreconditionCheckLocked() const; // State check only virtual status_t configureQueueLocked(); // State checks only virtual status_t disconnectLocked(); // Hand out the buffer to a native location, // incrementing the internal refcount and dequeued buffer count void handoutBufferLocked(camera3_stream_buffer &buffer, buffer_handle_t *handle, int acquire_fence, int release_fence, camera3_buffer_status_t status); }; // class Camera3IOStreamBase } // namespace camera3 } // namespace android #endif
services/camera/libcameraservice/camera3/Camera3InputStream.cpp +33 −160 Original line number Diff line number Diff line Loading @@ -18,9 +18,6 @@ #define ATRACE_TAG ATRACE_TAG_CAMERA //#define LOG_NDEBUG 0 // This is needed for stdint.h to define INT64_MAX in C++ #define __STDC_LIMIT_MACROS #include <utils/Log.h> #include <utils/Trace.h> #include "Camera3InputStream.h" Loading @@ -31,12 +28,8 @@ namespace camera3 { Camera3InputStream::Camera3InputStream(int id, uint32_t width, uint32_t height, int format) : Camera3Stream(id, CAMERA3_STREAM_INPUT, width, height, 0, format), mTotalBufferCount(0), mDequeuedBufferCount(0), mFrameCount(0), mLastTimestamp(0) { mCombinedFence = new Fence(); Camera3IOStreamBase(id, CAMERA3_STREAM_INPUT, width, height, /*maxSize*/0, format) { if (format == HAL_PIXEL_FORMAT_BLOB) { ALOGE("%s: Bad format, BLOB not supported", __FUNCTION__); Loading @@ -61,21 +54,8 @@ status_t Camera3InputStream::getInputBufferLocked( return INVALID_OPERATION; } // Allow acquire during IN_[RE]CONFIG for registration if (mState != STATE_CONFIGURED && mState != STATE_IN_CONFIG && mState != STATE_IN_RECONFIG) { ALOGE("%s: Stream %d: Can't get buffers in unconfigured state %d", __FUNCTION__, mId, mState); return INVALID_OPERATION; } // Only limit acquire amount when fully configured if (mState == STATE_CONFIGURED && mDequeuedBufferCount == camera3_stream::max_buffers) { ALOGE("%s: Stream %d: Already acquired maximum number of simultaneous" " buffers (%d)", __FUNCTION__, mId, camera3_stream::max_buffers); return INVALID_OPERATION; if ((res = getBufferPreconditionCheckLocked()) != OK) { return res; } ANativeWindowBuffer* anb; Loading @@ -95,51 +75,30 @@ status_t Camera3InputStream::getInputBufferLocked( anb = bufferItem.mGraphicBuffer->getNativeBuffer(); assert(anb != NULL); fenceFd = bufferItem.mFence->dup(); /** * FenceFD now owned by HAL except in case of error, * in which case we reassign it to acquire_fence */ // Handing out a raw pointer to this object. Increment internal refcount. incStrong(this); buffer->stream = this; buffer->buffer = &(anb->handle); buffer->acquire_fence = fenceFd; buffer->release_fence = -1; buffer->status = CAMERA3_BUFFER_STATUS_OK; mDequeuedBufferCount++; handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd, /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK); mBuffersInFlight.push_back(bufferItem); return OK; } status_t Camera3InputStream::returnInputBufferLocked( const camera3_stream_buffer &buffer) { ATRACE_CALL(); status_t res; status_t Camera3InputStream::returnBufferCheckedLocked( const camera3_stream_buffer &buffer, nsecs_t timestamp, bool output, /*out*/ sp<Fence> *releaseFenceOut) { // returnBuffer may be called from a raw pointer, not a sp<>, and we'll be // decrementing the internal refcount next. In case this is the last ref, we // might get destructed on the decStrong(), so keep an sp around until the // end of the call - otherwise have to sprinkle the decStrong on all exit // points. sp<Camera3InputStream> keepAlive(this); decStrong(this); // Allow buffers to be returned in the error state, to allow for disconnect // and in the in-config states for registration if (mState == STATE_CONSTRUCTED) { ALOGE("%s: Stream %d: Can't return buffers in unconfigured state %d", __FUNCTION__, mId, mState); return INVALID_OPERATION; } if (mDequeuedBufferCount == 0) { ALOGE("%s: Stream %d: No buffers outstanding to return", __FUNCTION__, mId); return INVALID_OPERATION; } (void)timestamp; (void)output; ALOG_ASSERT(!output, "Expected output to be false"); status_t res; bool bufferFound = false; BufferItem bufferItem; Loading Loading @@ -192,91 +151,24 @@ status_t Camera3InputStream::returnInputBufferLocked( return res; } mCombinedFence = Fence::merge(mName, mCombinedFence, releaseFence); mBufferReturnedSignal.signal(); *releaseFenceOut = releaseFence; return OK; } bool Camera3InputStream::hasOutstandingBuffersLocked() const { nsecs_t signalTime = mCombinedFence->getSignalTime(); ALOGV("%s: Stream %d: Has %d outstanding buffers," " buffer signal time is %lld", __FUNCTION__, mId, mDequeuedBufferCount, signalTime); if (mDequeuedBufferCount > 0 || signalTime == INT64_MAX) { return true; } return false; } status_t Camera3InputStream::waitUntilIdle(nsecs_t timeout) { status_t res; { Mutex::Autolock l(mLock); while (mDequeuedBufferCount > 0) { if (timeout != TIMEOUT_NEVER) { nsecs_t startTime = systemTime(); res = mBufferReturnedSignal.waitRelative(mLock, timeout); if (res == TIMED_OUT) { return res; } else if (res != OK) { ALOGE("%s: Error waiting for outstanding buffers: %s (%d)", __FUNCTION__, strerror(-res), res); return res; } nsecs_t deltaTime = systemTime() - startTime; if (timeout <= deltaTime) { timeout = 0; } else { timeout -= deltaTime; } } else { res = mBufferReturnedSignal.wait(mLock); if (res != OK) { ALOGE("%s: Error waiting for outstanding buffers: %s (%d)", __FUNCTION__, strerror(-res), res); return res; } } } } // No lock unsigned int timeoutMs; if (timeout == TIMEOUT_NEVER) { timeoutMs = Fence::TIMEOUT_NEVER; } else if (timeout == 0) { timeoutMs = 0; } else { // Round up to wait at least 1 ms timeoutMs = (timeout + 999999) / 1000000; } return mCombinedFence->wait(timeoutMs); } status_t Camera3InputStream::returnInputBufferLocked( const camera3_stream_buffer &buffer) { ATRACE_CALL(); size_t Camera3InputStream::getBufferCountLocked() { return mTotalBufferCount; return returnAnyBufferLocked(buffer, /*timestamp*/0, /*output*/false); } status_t Camera3InputStream::disconnectLocked() { switch (mState) { case STATE_IN_RECONFIG: case STATE_CONFIGURED: // OK break; default: // No connection, nothing to do return OK; } if (mDequeuedBufferCount > 0) { ALOGE("%s: Can't disconnect with %d buffers still acquired!", __FUNCTION__, mDequeuedBufferCount); return INVALID_OPERATION; status_t res; if ((res = Camera3IOStreamBase::disconnectLocked()) != OK) { return res; } assert(mBuffersInFlight.size() == 0); Loading @@ -285,7 +177,8 @@ status_t Camera3InputStream::disconnectLocked() { * no-op since we can't disconnect the producer from the consumer-side */ mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG : STATE_CONSTRUCTED; mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG : STATE_CONSTRUCTED; return OK; } Loading @@ -297,37 +190,17 @@ void Camera3InputStream::dump(int fd, const Vector<String16> &args) const { (void) args; String8 lines; lines.appendFormat(" Stream[%d]: Input\n", mId); lines.appendFormat(" State: %d\n", mState); lines.appendFormat(" Dims: %d x %d, format 0x%x\n", camera3_stream::width, camera3_stream::height, camera3_stream::format); lines.appendFormat(" Max size: %d\n", mMaxSize); lines.appendFormat(" Usage: %d, max HAL buffers: %d\n", camera3_stream::usage, camera3_stream::max_buffers); lines.appendFormat(" Frames produced: %d, last timestamp: %lld ns\n", mFrameCount, mLastTimestamp); lines.appendFormat(" Total buffers: %d, currently acquired: %d\n", mTotalBufferCount, mDequeuedBufferCount); write(fd, lines.string(), lines.size()); Camera3IOStreamBase::dump(fd, args); } status_t Camera3InputStream::configureQueueLocked() { status_t res; switch (mState) { case STATE_IN_RECONFIG: res = disconnectLocked(); if (res != OK) { if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) { return res; } break; case STATE_IN_CONFIG: // OK break; default: ALOGE("%s: Bad state: %d", __FUNCTION__, mState); return INVALID_OPERATION; } assert(mMaxSize == 0); assert(camera3_stream::format != HAL_PIXEL_FORMAT_BLOB); Loading
services/camera/libcameraservice/camera3/Camera3InputStream.h +11 −12 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ #include <gui/Surface.h> #include <gui/BufferItemConsumer.h> #include "Camera3Stream.h" #include "Camera3IOStreamBase.h" namespace android { Loading @@ -34,7 +34,7 @@ namespace camera3 { * buffers by feeding them into the HAL, as well as releasing the buffers back * the buffers once the HAL is done with them. */ class Camera3InputStream : public Camera3Stream { class Camera3InputStream : public Camera3IOStreamBase { public: /** * Set up a stream for formats that have fixed size, such as RAW and YUV. Loading @@ -42,7 +42,6 @@ class Camera3InputStream : public Camera3Stream { Camera3InputStream(int id, uint32_t width, uint32_t height, int format); ~Camera3InputStream(); virtual status_t waitUntilIdle(nsecs_t timeout); virtual void dump(int fd, const Vector<String16> &args) const; /** Loading @@ -58,14 +57,16 @@ class Camera3InputStream : public Camera3Stream { sp<BufferItemConsumer> mConsumer; Vector<BufferItem> mBuffersInFlight; size_t mTotalBufferCount; size_t mDequeuedBufferCount; Condition mBufferReturnedSignal; uint32_t mFrameCount; nsecs_t mLastTimestamp; // The merged release fence for all returned buffers sp<Fence> mCombinedFence; /** * Camera3IOStreamBase */ virtual status_t returnBufferCheckedLocked( const camera3_stream_buffer &buffer, nsecs_t timestamp, bool output, /*out*/ sp<Fence> *releaseFenceOut); /** * Camera3Stream interface Loading @@ -74,11 +75,9 @@ class Camera3InputStream : public Camera3Stream { virtual status_t getInputBufferLocked(camera3_stream_buffer *buffer); virtual status_t returnInputBufferLocked( const camera3_stream_buffer &buffer); virtual bool hasOutstandingBuffersLocked() const; virtual status_t disconnectLocked(); virtual status_t configureQueueLocked(); virtual size_t getBufferCountLocked(); }; // class Camera3InputStream Loading