Camera: implement buffer managment API

Test: compile
Bug: 109829698
Change-Id: I3d95792282da52db9db6fd6a086bbd7b3ff9dca9
gugelfrei
Yin-Chia Yeh 6 years ago
parent 0b28757873
commit d5cd5ffe3a

@ -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<void> Camera3Device::requestStreamBuffers(
const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& 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<std::mutex> lock(mRequestBufferInterfaceLock);
hardware::hidl_vec<StreamBufferRet> 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<int32_t> streamIds;
ssize_t sz = streamIds.setCapacity(bufReqs.size());
if (sz < 0 || static_cast<size_t>(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<StreamBufferRet> emptyBufRets;
_hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, emptyBufRets);
return hardware::Void();
}
sp<Camera3OutputStreamInterface> 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<StreamBuffer> tmpRetBuffers(numBuffersRequested);
bool currentReqSucceeds = true;
std::vector<camera3_stream_buffer_t> 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<void> Camera3Device::returnStreamBuffers(
const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& 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<void> 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<std::mutex> 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<std::mutex> 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<bool, uint64_t> Camera3Device::HalInterface::getBufferId(
const buffer_handle_t& buf, int streamId) {
std::lock_guard<std::mutex> lock(mBufferIdMapLock);
@ -4129,7 +4392,8 @@ void Camera3Device::HalInterface::onBufferFreed(
Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent,
sp<StatusTracker> statusTracker,
sp<HalInterface> interface, const Vector<int32_t>& sessionParamKeys) :
sp<HalInterface> interface, const Vector<int32_t>& sessionParamKeys,
bool useHalBufManager) :
Thread(/*canCallJava*/false),
mParent(parent),
mStatusTracker(statusTracker),
@ -4149,7 +4413,8 @@ Camera3Device::RequestThread::RequestThread(wp<Camera3Device> 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<Camera3Device*>(static_cast<const Camera3Device*>(cb));
d->processCaptureResult(result);
}
void Camera3Device::sNotify(const camera3_callback_ops *cb,
const camera3_notify_msg *msg) {
Camera3Device *d =
const_cast<Camera3Device*>(static_cast<const Camera3Device*>(cb));
d->notify(msg);
}
}; // namespace android

@ -33,10 +33,11 @@
#include <android/hardware/camera/device/3.2/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.3/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.2/ICameraDeviceCallback.h>
#include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
#include <fmq/MessageQueue.h>
#include <hardware/camera3.h>
#include <camera/CaptureResult.h>
@ -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<bool, uint64_t> 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<std::pair<int32_t, int32_t>>* out);
static const uint64_t BUFFER_ID_NO_BUFFER = 0;
private:
// Always valid
sp<hardware::camera::device::V3_2::ICameraDeviceSession> mHidlSession;
@ -314,6 +311,8 @@ class Camera3Device :
sp<hardware::camera::device::V3_3::ICameraDeviceSession> mHidlSession_3_3;
// Valid if ICameraDeviceSession is @3.4 or newer
sp<hardware::camera::device::V3_4::ICameraDeviceSession> mHidlSession_3_4;
// Valid if ICameraDeviceSession is @3.5 or newer
sp<hardware::camera::device::V3_5::ICameraDeviceSession> mHidlSession_3_5;
std::shared_ptr<RequestMetadataQueue> mRequestMetadataQueue;
@ -365,19 +364,14 @@ class Camera3Device :
// stream ID -> per stream buffer ID map
std::unordered_map<int, BufferIdMap> 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<bool, uint64_t> getBufferId(const buffer_handle_t& buf, int streamId);
virtual void onBufferFreed(int streamId, const native_handle_t* handle) override;
std::vector<std::pair<int, uint64_t>> mFreedBuffers;
// Buffers given to HAL through requestStreamBuffer API
std::mutex mRequestedBuffersLock;
std::unordered_map<uint64_t, buffer_handle_t*> mRequestedBuffers;
};
sp<HalInterface> 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<void> 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<void> requestStreamBuffers(
const hardware::hidl_vec<
hardware::camera::device::V3_5::BufferRequest>& bufReqs,
requestStreamBuffers_cb _hidl_cb) override;
hardware::Return<void> 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<Camera3Device> parent,
sp<camera3::StatusTracker> statusTracker,
sp<HalInterface> interface, const Vector<int32_t>& sessionParamKeys);
sp<HalInterface> interface,
const Vector<int32_t>& sessionParamKeys,
bool useHalBufManager);
~RequestThread();
void setNotificationListener(wp<NotificationListener> listener);
@ -937,6 +943,8 @@ class Camera3Device :
Vector<int32_t> mSessionParamKeys;
CameraMetadata mLatestSessionParams;
const bool mUseHalBufManager;
};
sp<RequestThread> mRequestThread;
@ -1020,7 +1028,7 @@ class Camera3Device :
InFlightRequest(int numBuffers, CaptureResultExtras extras, bool hasInput,
bool hasAppCallback, nsecs_t maxDuration,
const std::set<String8>& physicalCameraIdSet, bool isStillCapture,
const std::set<String8>& 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

@ -116,7 +116,7 @@ size_t Camera3IOStreamBase::getBufferCountLocked() {
return mTotalBufferCount;
}
size_t Camera3IOStreamBase::getHandoutOutputBufferCountLocked() {
size_t Camera3IOStreamBase::getHandoutOutputBufferCountLocked() const {
return mHandoutOutputBufferCount;
}

@ -82,7 +82,7 @@ class Camera3IOStreamBase :
virtual size_t getBufferCountLocked();
virtual size_t getHandoutOutputBufferCountLocked();
virtual size_t getHandoutOutputBufferCountLocked() const;
virtual size_t getHandoutInputBufferCountLocked();

@ -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.

@ -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> statusTracker) {
Mutex::Autolock l(mLock);
sp<StatusTracker> oldTracker = mStatusTracker.promote();

@ -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;

@ -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
};

Loading…
Cancel
Save