From d5cd5ffe3ada6b71818d9957bd7ca68b10e54268 Mon Sep 17 00:00:00 2001 From: Yin-Chia Yeh Date: Mon, 1 Oct 2018 14:43:04 -0700 Subject: [PATCH] Camera: implement buffer managment API Test: compile Bug: 109829698 Change-Id: I3d95792282da52db9db6fd6a086bbd7b3ff9dca9 --- .../device3/Camera3Device.cpp | 329 ++++++++++++++++-- .../libcameraservice/device3/Camera3Device.h | 80 +++-- .../device3/Camera3IOStreamBase.cpp | 2 +- .../device3/Camera3IOStreamBase.h | 2 +- .../device3/Camera3SharedOutputStream.cpp | 4 + .../device3/Camera3Stream.cpp | 6 + .../libcameraservice/device3/Camera3Stream.h | 7 +- .../device3/Camera3StreamInterface.h | 5 + 8 files changed, 360 insertions(+), 75 deletions(-) diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 2131cf8029..1d40d13c83 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -82,8 +82,6 @@ Camera3Device::Camera3Device(const String8 &id): mLastTemplateId(-1) { ATRACE_CALL(); - camera3_callback_ops::notify = &sNotify; - camera3_callback_ops::process_capture_result = &sProcessCaptureResult; ALOGV("%s: Created device for camera %s", __FUNCTION__, mId.string()); } @@ -218,8 +216,17 @@ status_t Camera3Device::initializeCommonLocked() { if (sessionKeysEntry.count > 0) { sessionParamKeys.insertArrayAt(sessionKeysEntry.data.i32, 0, sessionKeysEntry.count); } + + camera_metadata_entry bufMgrMode = + mDeviceInfo.find(ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION); + if (bufMgrMode.count > 0) { + mUseHalBufManager = (bufMgrMode.data.u8[0] == + ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5); + } + /** Start up request queue thread */ - mRequestThread = new RequestThread(this, mStatusTracker, mInterface, sessionParamKeys); + mRequestThread = new RequestThread( + this, mStatusTracker, mInterface, sessionParamKeys, mUseHalBufManager); res = mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string()); if (res != OK) { SET_ERR_L("Unable to start request queue thread: %s (%d)", @@ -271,7 +278,6 @@ status_t Camera3Device::initializeCommonLocked() { return res; } } - return OK; } @@ -919,6 +925,221 @@ status_t Camera3Device::submitRequestsHelper( return res; } +hardware::Return Camera3Device::requestStreamBuffers( + const hardware::hidl_vec& bufReqs, + requestStreamBuffers_cb _hidl_cb) { + using hardware::camera::device::V3_5::BufferRequestStatus; + using hardware::camera::device::V3_5::StreamBufferRet; + using hardware::camera::device::V3_5::StreamBufferRequestError; + + std::lock_guard lock(mRequestBufferInterfaceLock); + + hardware::hidl_vec bufRets; + if (!mUseHalBufManager) { + ALOGE("%s: Camera %s does not support HAL buffer management", + __FUNCTION__, mId.string()); + _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets); + return hardware::Void(); + } + + SortedVector streamIds; + ssize_t sz = streamIds.setCapacity(bufReqs.size()); + if (sz < 0 || static_cast(sz) != bufReqs.size()) { + ALOGE("%s: failed to allocate memory for %zu buffer requests", + __FUNCTION__, bufReqs.size()); + _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets); + return hardware::Void(); + } + + // Check for repeated streamId + for (const auto& bufReq : bufReqs) { + if (streamIds.indexOf(bufReq.streamId) != NAME_NOT_FOUND) { + ALOGE("%s: Stream %d appear multiple times in buffer requests", + __FUNCTION__, bufReq.streamId); + _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets); + return hardware::Void(); + } + streamIds.add(bufReq.streamId); + } + + // TODO: check we are not configuring streams. If so return FAILED_CONFIGURING + // Probably need to hook CameraDeviceClient::beginConfigure and figure something + // out for API1 client... maybe grab mLock and check mNeedConfig but then we will + // need to wait until mLock is released... + // _hidl_cb(BufferRequestStatus::FAILED_CONFIGURING, bufRets); + // return hardware::Void(); + + // TODO: here we start accessing mOutputStreams, might need mLock, but that + // might block incoming API calls. Not sure how bad is it. + if (bufReqs.size() > mOutputStreams.size()) { + ALOGE("%s: too many buffer requests (%zu > # of output streams %zu)", + __FUNCTION__, bufReqs.size(), mOutputStreams.size()); + _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets); + return hardware::Void(); + } + + bufRets.resize(bufReqs.size()); + + bool allReqsSucceeds = true; + bool oneReqSucceeds = false; + for (size_t i = 0; i < bufReqs.size(); i++) { + const auto& bufReq = bufReqs[i]; + auto& bufRet = bufRets[i]; + int32_t streamId = bufReq.streamId; + ssize_t idx = mOutputStreams.indexOfKey(streamId); + if (idx == NAME_NOT_FOUND) { + ALOGE("%s: Output stream id %d not found!", __FUNCTION__, streamId); + hardware::hidl_vec emptyBufRets; + _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, emptyBufRets); + return hardware::Void(); + } + sp outputStream = mOutputStreams.valueAt(idx); + + bufRet.streamId = streamId; + uint32_t numBuffersRequested = bufReq.numBuffersRequested; + size_t totalHandout = outputStream->getOutstandingBuffersCount() + numBuffersRequested; + if (totalHandout > outputStream->asHalStream()->max_buffers) { + // Not able to allocate enough buffer. Exit early for this stream + bufRet.val.error(StreamBufferRequestError::MAX_BUFFER_EXCEEDED); + allReqsSucceeds = false; + continue; + } + + hardware::hidl_vec tmpRetBuffers(numBuffersRequested); + bool currentReqSucceeds = true; + std::vector streamBuffers(numBuffersRequested); + size_t numAllocatedBuffers = 0; + size_t numPushedInflightBuffers = 0; + for (size_t b = 0; b < numBuffersRequested; b++) { + camera3_stream_buffer_t& sb = streamBuffers[b]; + // Since this method can run concurrently with request thread + // We need to update the wait duration everytime we call getbuffer + nsecs_t waitDuration = kBaseGetBufferWait + getExpectedInFlightDuration(); + status_t res = outputStream->getBuffer(&sb, waitDuration); + if (res != OK) { + ALOGE("%s: Can't get output buffer for stream %d: %s (%d)", + __FUNCTION__, streamId, strerror(-res), res); + if (res == NO_INIT || res == DEAD_OBJECT) { + bufRet.val.error(StreamBufferRequestError::STREAM_DISCONNECTED); + } else if (res == TIMED_OUT || res == NO_MEMORY) { + bufRet.val.error(StreamBufferRequestError::NO_BUFFER_AVAILABLE); + } else { + bufRet.val.error(StreamBufferRequestError::UNKNOWN_ERROR); + } + currentReqSucceeds = false; + break; + } + numAllocatedBuffers++; + + buffer_handle_t *buffer = sb.buffer; + auto pair = mInterface->getBufferId(*buffer, streamId); + bool isNewBuffer = pair.first; + uint64_t bufferId = pair.second; + StreamBuffer& hBuf = tmpRetBuffers[b]; + + hBuf.streamId = streamId; + hBuf.bufferId = bufferId; + hBuf.buffer = (isNewBuffer) ? *buffer : nullptr; + hBuf.status = BufferStatus::OK; + hBuf.releaseFence = nullptr; + + native_handle_t *acquireFence = nullptr; + if (sb.acquire_fence != -1) { + acquireFence = native_handle_create(1,0); + acquireFence->data[0] = sb.acquire_fence; + } + hBuf.acquireFence.setTo(acquireFence, /*shouldOwn*/true); + hBuf.releaseFence = nullptr; + + res = mInterface->pushInflightRequestBuffer(bufferId, buffer); + if (res != OK) { + ALOGE("%s: Can't get register request buffers for stream %d: %s (%d)", + __FUNCTION__, streamId, strerror(-res), res); + bufRet.val.error(StreamBufferRequestError::UNKNOWN_ERROR); + currentReqSucceeds = false; + break; + } + numPushedInflightBuffers++; + } + if (currentReqSucceeds) { + bufRet.val.buffers(std::move(tmpRetBuffers)); + oneReqSucceeds = true; + } else { + allReqsSucceeds = false; + for (size_t b = 0; b < numPushedInflightBuffers; b++) { + StreamBuffer& hBuf = tmpRetBuffers[b]; + buffer_handle_t* buffer; + status_t res = mInterface->popInflightRequestBuffer(hBuf.bufferId, &buffer); + if (res != OK) { + SET_ERR("%s: popInflightRequestBuffer failed for stream %d: %s (%d)", + __FUNCTION__, streamId, strerror(-res), res); + } + } + returnOutputBuffers(streamBuffers.data(), numAllocatedBuffers, 0); + } + } + // End of mOutputStreams access + + _hidl_cb(allReqsSucceeds ? BufferRequestStatus::OK : + oneReqSucceeds ? BufferRequestStatus::FAILED_PARTIAL : + BufferRequestStatus::FAILED_UNKNOWN, + bufRets); + return hardware::Void(); +} + +hardware::Return Camera3Device::returnStreamBuffers( + const hardware::hidl_vec& buffers) { + if (!mUseHalBufManager) { + ALOGE("%s: Camera %s does not support HAL buffer managerment", + __FUNCTION__, mId.string()); + return hardware::Void(); + } + + for (const auto& buf : buffers) { + if (buf.bufferId == HalInterface::BUFFER_ID_NO_BUFFER) { + ALOGE("%s: cannot return a buffer without bufferId", __FUNCTION__); + continue; + } + + buffer_handle_t* buffer; + status_t res = mInterface->popInflightRequestBuffer(buf.bufferId, &buffer); + + if (res != OK) { + ALOGE("%s: cannot find in-flight buffer %" PRIu64 " for stream %d", + __FUNCTION__, buf.bufferId, buf.streamId); + continue; + } + + camera3_stream_buffer_t streamBuffer; + streamBuffer.buffer = buffer; + streamBuffer.status = CAMERA3_BUFFER_STATUS_ERROR; + streamBuffer.acquire_fence = -1; + streamBuffer.release_fence = -1; + + if (buf.releaseFence == nullptr) { + streamBuffer.release_fence = -1; + } else if (buf.releaseFence->numFds == 1) { + streamBuffer.release_fence = dup(buf.releaseFence->data[0]); + } else { + ALOGE("%s: Invalid release fence, fd count is %d, not 1", + __FUNCTION__, buf.releaseFence->numFds); + continue; + } + + // Need to lock mLock here if we were to allow HAL to return buffer during + // stream configuration. This is not currently possible because we only + // do stream configuration when there is no inflight buffers in HAL. + ssize_t idx = mOutputStreams.indexOfKey(buf.streamId); + if (idx == NAME_NOT_FOUND) { + ALOGE("%s: Output stream id %d not found!", __FUNCTION__, buf.streamId); + continue; + } + streamBuffer.stream = mOutputStreams.valueAt(idx)->asHalStream(); + returnOutputBuffers(&streamBuffer, /*size*/1, /*timestamp*/ 0); + } + return hardware::Void(); +} + hardware::Return Camera3Device::processCaptureResult_3_4( const hardware::hidl_vec< hardware::camera::device::V3_4::CaptureResult>& results) { @@ -1076,12 +1297,23 @@ void Camera3Device::processOneCaptureResultLocked( bDst.stream = mOutputStreams.valueAt(idx)->asHalStream(); buffer_handle_t *buffer; - res = mInterface->popInflightBuffer(result.frameNumber, bSrc.streamId, &buffer); + if (mUseHalBufManager) { + if (bSrc.bufferId == HalInterface::BUFFER_ID_NO_BUFFER) { + ALOGE("%s: Frame %d: Buffer %zu: No bufferId for stream %d", + __FUNCTION__, result.frameNumber, i, bSrc.streamId); + return; + } + res = mInterface->popInflightRequestBuffer(bSrc.bufferId, &buffer); + } else { + res = mInterface->popInflightBuffer(result.frameNumber, bSrc.streamId, &buffer); + } + if (res != OK) { ALOGE("%s: Frame %d: Buffer %zu: No in-flight buffer for stream %d", __FUNCTION__, result.frameNumber, i, bSrc.streamId); return; } + bDst.buffer = buffer; bDst.status = mapHidlBufferStatus(bSrc.status); bDst.acquire_fence = -1; @@ -3475,6 +3707,10 @@ Camera3Device::HalInterface::HalInterface( mRequestMetadataQueue(queue) { // Check with hardware service manager if we can downcast these interfaces // Somewhat expensive, so cache the results at startup + auto castResult_3_5 = device::V3_5::ICameraDeviceSession::castFrom(mHidlSession); + if (castResult_3_5.isOk()) { + mHidlSession_3_5 = castResult_3_5; + } auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession); if (castResult_3_4.isOk()) { mHidlSession_3_4 = castResult_3_4; @@ -4081,6 +4317,33 @@ status_t Camera3Device::HalInterface::popInflightBuffer( return OK; } +status_t Camera3Device::HalInterface::pushInflightRequestBuffer( + uint64_t bufferId, buffer_handle_t* buf) { + std::lock_guard lock(mRequestedBuffersLock); + auto pair = mRequestedBuffers.insert({bufferId, buf}); + if (!pair.second) { + ALOGE("%s: bufId %" PRIu64 " is already inflight!", + __FUNCTION__, bufferId); + return BAD_VALUE; + } + return OK; +} + +// Find and pop a buffer_handle_t based on bufferId +status_t Camera3Device::HalInterface::popInflightRequestBuffer( + uint64_t bufferId, /*out*/ buffer_handle_t **buffer) { + std::lock_guard lock(mRequestedBuffersLock); + auto it = mRequestedBuffers.find(bufferId); + if (it == mRequestedBuffers.end()) { + ALOGE("%s: bufId %" PRIu64 " is not inflight!", + __FUNCTION__, bufferId); + return BAD_VALUE; + } + *buffer = it->second; + mRequestedBuffers.erase(it); + return OK; +} + std::pair Camera3Device::HalInterface::getBufferId( const buffer_handle_t& buf, int streamId) { std::lock_guard lock(mBufferIdMapLock); @@ -4129,7 +4392,8 @@ void Camera3Device::HalInterface::onBufferFreed( Camera3Device::RequestThread::RequestThread(wp parent, sp statusTracker, - sp interface, const Vector& sessionParamKeys) : + sp interface, const Vector& sessionParamKeys, + bool useHalBufManager) : Thread(/*canCallJava*/false), mParent(parent), mStatusTracker(statusTracker), @@ -4149,7 +4413,8 @@ Camera3Device::RequestThread::RequestThread(wp parent, mConstrainedMode(false), mRequestLatency(kRequestLatencyBinSize), mSessionParamKeys(sessionParamKeys), - mLatestSessionParams(sessionParamKeys.size()) { + mLatestSessionParams(sessionParamKeys.size()), + mUseHalBufManager(useHalBufManager) { mStatusId = statusTracker->addComponent(); } @@ -4928,16 +5193,27 @@ status_t Camera3Device::RequestThread::prepareHalRequests() { } } - res = outputStream->getBuffer(&outputBuffers->editItemAt(j), - waitDuration, - captureRequest->mOutputSurfaces[outputStream->getId()]); - if (res != OK) { - // Can't get output buffer from gralloc queue - this could be due to - // abandoned queue or other consumer misbehavior, so not a fatal - // error - ALOGE("RequestThread: Can't get output buffer, skipping request:" - " %s (%d)", strerror(-res), res); - return TIMED_OUT; + if (mUseHalBufManager) { + // HAL will request buffer through requestStreamBuffer API + camera3_stream_buffer_t& buffer = outputBuffers->editItemAt(j); + buffer.stream = outputStream->asHalStream(); + buffer.buffer = nullptr; + buffer.status = CAMERA3_BUFFER_STATUS_OK; + buffer.acquire_fence = -1; + buffer.release_fence = -1; + } else { + res = outputStream->getBuffer(&outputBuffers->editItemAt(j), + waitDuration, + captureRequest->mOutputSurfaces[outputStream->getId()]); + if (res != OK) { + // Can't get output buffer from gralloc queue - this could be due to + // abandoned queue or other consumer misbehavior, so not a fatal + // error + ALOGE("RequestThread: Can't get output buffer, skipping request:" + " %s (%d)", strerror(-res), res); + + return TIMED_OUT; + } } String8 physicalCameraId = outputStream->getPhysicalCameraId(); @@ -5794,23 +6070,4 @@ bool Camera3Device::PreparerThread::threadLoop() { return true; } -/** - * Static callback forwarding methods from HAL to instance - */ - -void Camera3Device::sProcessCaptureResult(const camera3_callback_ops *cb, - const camera3_capture_result *result) { - Camera3Device *d = - const_cast(static_cast(cb)); - - d->processCaptureResult(result); -} - -void Camera3Device::sNotify(const camera3_callback_ops *cb, - const camera3_notify_msg *msg) { - Camera3Device *d = - const_cast(static_cast(cb)); - d->notify(msg); -} - }; // namespace android diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h index 5e749b6d48..7656ef33cd 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.h +++ b/services/camera/libcameraservice/device3/Camera3Device.h @@ -33,10 +33,11 @@ #include #include #include +#include #include #include +#include #include -#include #include @@ -50,20 +51,6 @@ using android::camera3::OutputStreamInfo; -/** - * Function pointer types with C calling convention to - * use for HAL callback functions. - */ -extern "C" { - typedef void (callbacks_process_capture_result_t)( - const struct camera3_callback_ops *, - const camera3_capture_result_t *); - - typedef void (callbacks_notify_t)( - const struct camera3_callback_ops *, - const camera3_notify_msg_t *); -} - namespace android { namespace camera3 { @@ -80,8 +67,7 @@ class Camera3StreamInterface; */ class Camera3Device : public CameraDeviceBase, - virtual public hardware::camera::device::V3_4::ICameraDeviceCallback, - private camera3_callback_ops { + virtual public hardware::camera::device::V3_5::ICameraDeviceCallback { public: explicit Camera3Device(const String8& id); @@ -299,14 +285,25 @@ class Camera3Device : status_t dump(int fd); status_t close(); + // method to extract buffer's unique ID + // return pair of (newlySeenBuffer?, bufferId) + std::pair getBufferId(const buffer_handle_t& buf, int streamId); + // Find a buffer_handle_t based on frame number and stream ID status_t popInflightBuffer(int32_t frameNumber, int32_t streamId, /*out*/ buffer_handle_t **buffer); + // Register a bufId/buffer_handle_t to inflight request buffer + status_t pushInflightRequestBuffer(uint64_t bufferId, buffer_handle_t* buf); + + // Find a buffer_handle_t based on bufferId + status_t popInflightRequestBuffer(uint64_t bufferId, /*out*/ buffer_handle_t **buffer); + // Get a vector of (frameNumber, streamId) pair of currently inflight // buffers void getInflightBufferKeys(std::vector>* out); + static const uint64_t BUFFER_ID_NO_BUFFER = 0; private: // Always valid sp mHidlSession; @@ -314,6 +311,8 @@ class Camera3Device : sp mHidlSession_3_3; // Valid if ICameraDeviceSession is @3.4 or newer sp mHidlSession_3_4; + // Valid if ICameraDeviceSession is @3.5 or newer + sp mHidlSession_3_5; std::shared_ptr mRequestMetadataQueue; @@ -365,19 +364,14 @@ class Camera3Device : // stream ID -> per stream buffer ID map std::unordered_map mBufferIdMaps; uint64_t mNextBufferId = 1; // 0 means no buffer - static const uint64_t BUFFER_ID_NO_BUFFER = 0; - - // method to extract buffer's unique ID - // TODO: we should switch to use gralloc mapper's getBackingStore API - // once we ran in binderized gralloc mode, but before that is ready, - // we need to rely on the conventional buffer queue behavior where - // buffer_handle_t's FD won't change. - // return pair of (newlySeenBuffer?, bufferId) - std::pair getBufferId(const buffer_handle_t& buf, int streamId); virtual void onBufferFreed(int streamId, const native_handle_t* handle) override; std::vector> mFreedBuffers; + + // Buffers given to HAL through requestStreamBuffer API + std::mutex mRequestedBuffersLock; + std::unordered_map mRequestedBuffers; }; sp mInterface; @@ -483,8 +477,9 @@ class Camera3Device : /** - * Implementation of android::hardware::camera::device::V3_4::ICameraDeviceCallback + * Implementation of android::hardware::camera::device::V3_5::ICameraDeviceCallback */ + hardware::Return processCaptureResult_3_4( const hardware::hidl_vec< hardware::camera::device::V3_4::CaptureResult>& results) override; @@ -495,6 +490,15 @@ class Camera3Device : const hardware::hidl_vec< hardware::camera::device::V3_2::NotifyMsg>& msgs) override; + hardware::Return requestStreamBuffers( + const hardware::hidl_vec< + hardware::camera::device::V3_5::BufferRequest>& bufReqs, + requestStreamBuffers_cb _hidl_cb) override; + + hardware::Return returnStreamBuffers( + const hardware::hidl_vec< + hardware::camera::device::V3_2::StreamBuffer>& buffers) override; + // Handle one capture result. Assume that mProcessCaptureResultLock is held. void processOneCaptureResultLocked( const hardware::camera::device::V3_2::CaptureResult& result, @@ -702,7 +706,9 @@ class Camera3Device : RequestThread(wp parent, sp statusTracker, - sp interface, const Vector& sessionParamKeys); + sp interface, + const Vector& sessionParamKeys, + bool useHalBufManager); ~RequestThread(); void setNotificationListener(wp listener); @@ -937,6 +943,8 @@ class Camera3Device : Vector mSessionParamKeys; CameraMetadata mLatestSessionParams; + + const bool mUseHalBufManager; }; sp mRequestThread; @@ -1020,7 +1028,7 @@ class Camera3Device : InFlightRequest(int numBuffers, CaptureResultExtras extras, bool hasInput, bool hasAppCallback, nsecs_t maxDuration, - const std::set& physicalCameraIdSet, bool isStillCapture, + const std::set& physicalCameraIdSet, bool isStillCapture, bool isZslCapture) : shutterTimestamp(0), sensorTimestamp(0), @@ -1217,16 +1225,16 @@ class Camera3Device : // Cached last requested template id int mLastTemplateId; - /** - * Static callback forwarding methods from HAL to instance - */ - static callbacks_process_capture_result_t sProcessCaptureResult; - - static callbacks_notify_t sNotify; - // Synchronizes access to status tracker between inflight updates and disconnect. // b/79972865 Mutex mTrackerLock; + + // Whether HAL request buffers through requestStreamBuffer API + bool mUseHalBufManager = false; + + // Lock to ensure requestStreamBuffers() callbacks are serialized + std::mutex mRequestBufferInterfaceLock; + }; // class Camera3Device }; // namespace android diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp index 3c1e43d9b4..18b8c4d613 100644 --- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp +++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp @@ -116,7 +116,7 @@ size_t Camera3IOStreamBase::getBufferCountLocked() { return mTotalBufferCount; } -size_t Camera3IOStreamBase::getHandoutOutputBufferCountLocked() { +size_t Camera3IOStreamBase::getHandoutOutputBufferCountLocked() const { return mHandoutOutputBufferCount; } diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h index 0a31d444b9..48e9bbf846 100644 --- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h +++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h @@ -82,7 +82,7 @@ class Camera3IOStreamBase : virtual size_t getBufferCountLocked(); - virtual size_t getHandoutOutputBufferCountLocked(); + virtual size_t getHandoutOutputBufferCountLocked() const; virtual size_t getHandoutInputBufferCountLocked(); diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp index fb3ce4c619..1c13950950 100644 --- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp +++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp @@ -138,6 +138,10 @@ status_t Camera3SharedOutputStream::getBufferLocked(camera3_stream_buffer *buffe return res; } + // TODO: need to refactor this to support requestStreamBuffers API + // Need to wait until processCaptureResult to decide the source buffer + // to attach to output... + // Attach the buffer to the splitter output queues. This could block if // the output queue doesn't have any empty slot. So unlock during the course // of attachBufferToOutputs. diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp index ee989e12ed..0a30a97631 100644 --- a/services/camera/libcameraservice/device3/Camera3Stream.cpp +++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp @@ -795,6 +795,12 @@ bool Camera3Stream::hasOutstandingBuffers() const { return hasOutstandingBuffersLocked(); } +size_t Camera3Stream::getOutstandingBuffersCount() const { + ATRACE_CALL(); + Mutex::Autolock l(mLock); + return getHandoutOutputBufferCountLocked(); +} + status_t Camera3Stream::setStatusTracker(sp statusTracker) { Mutex::Autolock l(mLock); sp oldTracker = mStatusTracker.promote(); diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h index 1c67fb2e74..e29c3e00ae 100644 --- a/services/camera/libcameraservice/device3/Camera3Stream.h +++ b/services/camera/libcameraservice/device3/Camera3Stream.h @@ -360,6 +360,11 @@ class Camera3Stream : */ bool hasOutstandingBuffers() const; + /** + * Get number of buffers currently handed out to HAL + */ + size_t getOutstandingBuffersCount() const; + enum { TIMEOUT_NEVER = -1 }; @@ -495,7 +500,7 @@ class Camera3Stream : virtual size_t getBufferCountLocked() = 0; // Get handout output buffer count. - virtual size_t getHandoutOutputBufferCountLocked() = 0; + virtual size_t getHandoutOutputBufferCountLocked() const = 0; // Get handout input buffer count. virtual size_t getHandoutInputBufferCountLocked() = 0; diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h index 5758ac8203..866b7224f8 100644 --- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h +++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h @@ -289,6 +289,11 @@ class Camera3StreamInterface : public virtual RefBase { */ virtual bool hasOutstandingBuffers() const = 0; + /** + * Get number of buffers currently handed out to HAL + */ + virtual size_t getOutstandingBuffersCount() const = 0; + enum { TIMEOUT_NEVER = -1 };