summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorChien-Yu Chen <cychen@google.com>2015-04-14 17:29:40 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-04-14 17:29:41 +0000
commit2f33dbc6ca08d45efea2df775c158e2a11e07ab6 (patch)
treeb465e416af6302e7e0dda0826c9766f33bbc2cfc /services
parentb23cabdb71b98dc5e852f5d06be271696fea92c7 (diff)
parent618ff8a48a0c895a78f91f5692510c2a809425c3 (diff)
downloadframeworks_av-2f33dbc6ca08d45efea2df775c158e2a11e07ab6.zip
frameworks_av-2f33dbc6ca08d45efea2df775c158e2a11e07ab6.tar.gz
frameworks_av-2f33dbc6ca08d45efea2df775c158e2a11e07ab6.tar.bz2
Merge "camera2: add reprocess support"
Diffstat (limited to 'services')
-rw-r--r--services/camera/libcameraservice/api2/CameraDeviceClient.cpp117
-rw-r--r--services/camera/libcameraservice/api2/CameraDeviceClient.h19
-rw-r--r--services/camera/libcameraservice/common/CameraDeviceBase.h13
-rw-r--r--services/camera/libcameraservice/device2/Camera2Device.cpp14
-rw-r--r--services/camera/libcameraservice/device2/Camera2Device.h4
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.cpp67
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.h27
-rw-r--r--services/camera/libcameraservice/device3/Camera3InputStream.cpp28
-rw-r--r--services/camera/libcameraservice/device3/Camera3InputStream.h3
-rw-r--r--services/camera/libcameraservice/device3/Camera3OutputStream.cpp16
-rw-r--r--services/camera/libcameraservice/device3/Camera3Stream.cpp11
-rw-r--r--services/camera/libcameraservice/device3/Camera3Stream.h7
-rw-r--r--services/camera/libcameraservice/device3/Camera3StreamInterface.h7
13 files changed, 296 insertions, 37 deletions
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 8587e0e..0016174 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -65,6 +65,7 @@ CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
int servicePid) :
Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, cameraFacing, clientPid, clientUid, servicePid),
+ mInputStream(),
mRequestIdCounter(0) {
ATRACE_CALL();
@@ -127,6 +128,7 @@ status_t CameraDeviceClient::submitRequestList(List<sp<CaptureRequest> > request
List<const CameraMetadata> metadataRequestList;
int32_t requestId = mRequestIdCounter;
uint32_t loopCounter = 0;
+ bool isReprocess = false;
for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end(); ++it) {
sp<CaptureRequest> request = *it;
@@ -134,6 +136,18 @@ status_t CameraDeviceClient::submitRequestList(List<sp<CaptureRequest> > request
ALOGE("%s: Camera %d: Sent null request.",
__FUNCTION__, mCameraId);
return BAD_VALUE;
+ } else if (it == requests.begin()) {
+ isReprocess = request->mIsReprocess;
+ if (isReprocess && !mInputStream.configured) {
+ ALOGE("%s: Camera %d: no input stream is configured.");
+ return BAD_VALUE;
+ } else if (isReprocess && streaming) {
+ ALOGE("%s: Camera %d: streaming reprocess requests not supported.");
+ return BAD_VALUE;
+ }
+ } else if (isReprocess != request->mIsReprocess) {
+ ALOGE("%s: Camera %d: Sent regular and reprocess requests.");
+ return BAD_VALUE;
}
CameraMetadata metadata(request->mMetadata);
@@ -182,6 +196,10 @@ status_t CameraDeviceClient::submitRequestList(List<sp<CaptureRequest> > request
metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS, &outputStreamIds[0],
outputStreamIds.size());
+ if (isReprocess) {
+ metadata.update(ANDROID_REQUEST_INPUT_STREAMS, &mInputStream.id, 1);
+ }
+
metadata.update(ANDROID_REQUEST_ID, &requestId, /*size*/1);
loopCounter++; // loopCounter starts from 1
ALOGV("%s: Camera %d: Creating request with ID %d (%d of %zu)",
@@ -260,8 +278,8 @@ status_t CameraDeviceClient::beginConfigure() {
}
status_t CameraDeviceClient::endConfigure() {
- ALOGV("%s: ending configure (%zu streams)",
- __FUNCTION__, mStreamMap.size());
+ ALOGV("%s: ending configure (%d input stream, %zu output streams)",
+ __FUNCTION__, mInputStream.configured ? 1 : 0, mStreamMap.size());
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
@@ -284,19 +302,25 @@ status_t CameraDeviceClient::deleteStream(int streamId) {
if (!mDevice.get()) return DEAD_OBJECT;
- // Guard against trying to delete non-created streams
+ bool isInput = false;
ssize_t index = NAME_NOT_FOUND;
- for (size_t i = 0; i < mStreamMap.size(); ++i) {
- if (streamId == mStreamMap.valueAt(i)) {
- index = i;
- break;
+
+ if (mInputStream.configured && mInputStream.id == streamId) {
+ isInput = true;
+ } else {
+ // Guard against trying to delete non-created streams
+ for (size_t i = 0; i < mStreamMap.size(); ++i) {
+ if (streamId == mStreamMap.valueAt(i)) {
+ index = i;
+ break;
+ }
}
- }
- if (index == NAME_NOT_FOUND) {
- ALOGW("%s: Camera %d: Invalid stream ID (%d) specified, no stream "
- "created yet", __FUNCTION__, mCameraId, streamId);
- return BAD_VALUE;
+ if (index == NAME_NOT_FOUND) {
+ ALOGW("%s: Camera %d: Invalid stream ID (%d) specified, no stream "
+ "created yet", __FUNCTION__, mCameraId, streamId);
+ return BAD_VALUE;
+ }
}
// Also returns BAD_VALUE if stream ID was not valid
@@ -307,8 +331,11 @@ status_t CameraDeviceClient::deleteStream(int streamId) {
" already checked and the stream ID (%d) should be valid.",
__FUNCTION__, mCameraId, streamId);
} else if (res == OK) {
- mStreamMap.removeItemsAt(index);
-
+ if (isInput) {
+ mInputStream.configured = false;
+ } else {
+ mStreamMap.removeItemsAt(index);
+ }
}
return res;
@@ -450,6 +477,58 @@ status_t CameraDeviceClient::createStream(const OutputConfiguration &outputConfi
}
+status_t CameraDeviceClient::createInputStream(int width, int height,
+ int format) {
+
+ ATRACE_CALL();
+ ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
+
+ status_t res;
+ if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
+
+ Mutex::Autolock icl(mBinderSerializationLock);
+ if (!mDevice.get()) return DEAD_OBJECT;
+
+ if (mInputStream.configured) {
+ ALOGE("%s: Camera %d: Already has an input stream "
+ " configuration. (ID %zd)", __FUNCTION__, mCameraId,
+ mInputStream.id);
+ return ALREADY_EXISTS;
+ }
+
+ int streamId = -1;
+ res = mDevice->createInputStream(width, height, format, &streamId);
+ if (res == OK) {
+ mInputStream.configured = true;
+ mInputStream.width = width;
+ mInputStream.height = height;
+ mInputStream.format = format;
+ mInputStream.id = streamId;
+
+ ALOGV("%s: Camera %d: Successfully created a new input stream ID %d",
+ __FUNCTION__, mCameraId, streamId);
+
+ return streamId;
+ }
+
+ return res;
+}
+
+status_t CameraDeviceClient::getInputBufferProducer(
+ /*out*/sp<IGraphicBufferProducer> *producer) {
+ status_t res;
+ if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
+
+ if (producer == NULL) {
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock icl(mBinderSerializationLock);
+ if (!mDevice.get()) return DEAD_OBJECT;
+
+ return mDevice->getInputBufferProducer(producer);
+}
+
bool CameraDeviceClient::roundBufferDimensionNearest(int32_t width, int32_t height,
int32_t format, android_dataspace dataSpace, const CameraMetadata& info,
/*out*/int32_t* outWidth, /*out*/int32_t* outHeight) {
@@ -602,13 +681,19 @@ status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) {
result.append(" State:\n");
result.appendFormat(" Request ID counter: %d\n", mRequestIdCounter);
+ if (mInputStream.configured) {
+ result.appendFormat(" Current input stream ID: %d\n",
+ mInputStream.id);
+ } else {
+ result.append(" No input stream configured.\n");
+ }
if (!mStreamMap.isEmpty()) {
- result.append(" Current stream IDs:\n");
+ result.append(" Current output stream IDs:\n");
for (size_t i = 0; i < mStreamMap.size(); i++) {
result.appendFormat(" Stream %d\n", mStreamMap.valueAt(i));
}
} else {
- result.append(" No streams configured.\n");
+ result.append(" No output streams configured.\n");
}
write(fd, result.string(), result.size());
// TODO: print dynamic/request section from most recent requests
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index a3dbb90..f2d8899 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -86,6 +86,13 @@ public:
virtual status_t createStream(const OutputConfiguration &outputConfiguration);
+ // Create an input stream of width, height, and format.
+ virtual status_t createInputStream(int width, int height, int format);
+
+ // Get the buffer producer of the input stream
+ virtual status_t getInputBufferProducer(
+ /*out*/sp<IGraphicBufferProducer> *producer);
+
// Create a request object from a template.
virtual status_t createDefaultRequest(int templateId,
/*out*/
@@ -161,10 +168,18 @@ private:
android_dataspace dataSpace, const CameraMetadata& info,
/*out*/int32_t* outWidth, /*out*/int32_t* outHeight);
- // IGraphicsBufferProducer binder -> Stream ID
+ // IGraphicsBufferProducer binder -> Stream ID for output streams
KeyedVector<sp<IBinder>, int> mStreamMap;
- // Stream ID
+ struct InputStreamConfiguration {
+ bool configured;
+ int32_t width;
+ int32_t height;
+ int32_t format;
+ int32_t id;
+ } mInputStream;
+
+ // Request ID
Vector<int> mStreamingRequestList;
int32_t mRequestIdCounter;
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index fe55b9e..6ece359 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -30,6 +30,7 @@
#include "camera/CameraMetadata.h"
#include "camera/CaptureResult.h"
#include "common/CameraModule.h"
+#include "gui/IGraphicBufferProducer.h"
namespace android {
@@ -110,6 +111,14 @@ class CameraDeviceBase : public virtual RefBase {
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id) = 0;
/**
+ * Create an input stream of width, height, and format.
+ *
+ * Return value is the stream ID if non-negative and an error if negative.
+ */
+ virtual status_t createInputStream(uint32_t width, uint32_t height,
+ int32_t format, /*out*/ int32_t *id) = 0;
+
+ /**
* Create an input reprocess stream that uses buffers from an existing
* output stream.
*/
@@ -150,6 +159,10 @@ class CameraDeviceBase : public virtual RefBase {
*/
virtual status_t configureStreams() = 0;
+ // get the buffer producer of the input stream
+ virtual status_t getInputBufferProducer(
+ sp<IGraphicBufferProducer> *producer) = 0;
+
/**
* Create a metadata buffer with fields that the HAL device believes are
* best for the given use case
diff --git a/services/camera/libcameraservice/device2/Camera2Device.cpp b/services/camera/libcameraservice/device2/Camera2Device.cpp
index 878986b..3c5ea9d 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.cpp
+++ b/services/camera/libcameraservice/device2/Camera2Device.cpp
@@ -1581,4 +1581,18 @@ int Camera2Device::ReprocessStreamAdapter::release_buffer(
return OK;
}
+// camera 2 devices don't support reprocessing
+status_t Camera2Device::createInputStream(
+ uint32_t width, uint32_t height, int format, int *id) {
+ ALOGE("%s: camera 2 devices don't support reprocessing", __FUNCTION__);
+ return INVALID_OPERATION;
+}
+
+// camera 2 devices don't support reprocessing
+status_t Camera2Device::getInputBufferProducer(
+ sp<IGraphicBufferProducer> *producer) {
+ ALOGE("%s: camera 2 devices don't support reprocessing", __FUNCTION__);
+ return INVALID_OPERATION;
+}
+
}; // namespace android
diff --git a/services/camera/libcameraservice/device2/Camera2Device.h b/services/camera/libcameraservice/device2/Camera2Device.h
index 9b32fa6..9972606 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.h
+++ b/services/camera/libcameraservice/device2/Camera2Device.h
@@ -59,6 +59,8 @@ class Camera2Device: public CameraDeviceBase {
virtual status_t createStream(sp<ANativeWindow> consumer,
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id);
+ virtual status_t createInputStream(
+ uint32_t width, uint32_t height, int format, int *id);
virtual status_t createReprocessStreamFromStream(int outputId, int *id);
virtual status_t getStreamInfo(int id,
uint32_t *width, uint32_t *height, uint32_t *format);
@@ -67,6 +69,8 @@ class Camera2Device: public CameraDeviceBase {
virtual status_t deleteReprocessStream(int id);
// No-op on HAL2 devices
virtual status_t configureStreams();
+ virtual status_t getInputBufferProducer(
+ sp<IGraphicBufferProducer> *producer);
virtual status_t createDefaultRequest(int templateId, CameraMetadata *request);
virtual status_t waitUntilDrained();
virtual status_t setNotifyCallback(NotificationListener *listener);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 8236788..dc752a6 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -62,6 +62,7 @@ Camera3Device::Camera3Device(int id):
mUsePartialResult(false),
mNumPartialResults(1),
mNextResultFrameNumber(0),
+ mNextReprocessResultFrameNumber(0),
mNextShutterFrameNumber(0),
mListener(NULL)
{
@@ -201,6 +202,17 @@ status_t Camera3Device::initialize(CameraModule *module)
}
}
+ camera_metadata_entry configs =
+ mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
+ for (uint32_t i = 0; i < configs.count; i += 4) {
+ if (configs.data.i32[i] == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
+ configs.data.i32[i + 3] ==
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {
+ mSupportedOpaqueInputSizes.add(Size(configs.data.i32[i + 1],
+ configs.data.i32[i + 2]));
+ }
+ }
+
return OK;
}
@@ -1019,6 +1031,20 @@ status_t Camera3Device::configureStreams() {
return configureStreamsLocked();
}
+status_t Camera3Device::getInputBufferProducer(
+ sp<IGraphicBufferProducer> *producer) {
+ Mutex::Autolock il(mInterfaceLock);
+ Mutex::Autolock l(mLock);
+
+ if (producer == NULL) {
+ return BAD_VALUE;
+ } else if (mInputStream == NULL) {
+ return INVALID_OPERATION;
+ }
+
+ return mInputStream->getInputBufferProducer(producer);
+}
+
status_t Camera3Device::createDefaultRequest(int templateId,
CameraMetadata *request) {
ATRACE_CALL();
@@ -1423,6 +1449,17 @@ sp<Camera3Device::CaptureRequest> Camera3Device::createCaptureRequest(
return newRequest;
}
+bool Camera3Device::isOpaqueInputSizeSupported(uint32_t width, uint32_t height) {
+ for (uint32_t i = 0; i < mSupportedOpaqueInputSizes.size(); i++) {
+ Size size = mSupportedOpaqueInputSizes[i];
+ if (size.width == width && size.height == height) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
status_t Camera3Device::configureStreamsLocked() {
ATRACE_CALL();
status_t res;
@@ -1947,20 +1984,31 @@ void Camera3Device::removeInFlightRequestIfReadyLocked(int idx) {
void Camera3Device::sendCaptureResult(CameraMetadata &pendingMetadata,
CaptureResultExtras &resultExtras,
CameraMetadata &collectedPartialResult,
- uint32_t frameNumber) {
+ uint32_t frameNumber,
+ bool reprocess) {
if (pendingMetadata.isEmpty())
return;
Mutex::Autolock l(mOutputLock);
// TODO: need to track errors for tighter bounds on expected frame number
- if (frameNumber < mNextResultFrameNumber) {
- SET_ERR("Out-of-order capture result metadata submitted! "
+ if (reprocess) {
+ if (frameNumber < mNextReprocessResultFrameNumber) {
+ SET_ERR("Out-of-order reprocess capture result metadata submitted! "
"(got frame number %d, expecting %d)",
- frameNumber, mNextResultFrameNumber);
- return;
+ frameNumber, mNextReprocessResultFrameNumber);
+ return;
+ }
+ mNextReprocessResultFrameNumber = frameNumber + 1;
+ } else {
+ if (frameNumber < mNextResultFrameNumber) {
+ SET_ERR("Out-of-order capture result metadata submitted! "
+ "(got frame number %d, expecting %d)",
+ frameNumber, mNextResultFrameNumber);
+ return;
+ }
+ mNextResultFrameNumber = frameNumber + 1;
}
- mNextResultFrameNumber = frameNumber + 1;
CaptureResult captureResult;
captureResult.mResultExtras = resultExtras;
@@ -2170,7 +2218,7 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
CameraMetadata metadata;
metadata = result->result;
sendCaptureResult(metadata, request.resultExtras,
- collectedPartialResult, frameNumber);
+ collectedPartialResult, frameNumber, hasInputBufferInRequest);
}
}
@@ -2332,7 +2380,8 @@ void Camera3Device::notifyShutter(const camera3_shutter_msg_t &msg,
// send pending result and buffers
sendCaptureResult(r.pendingMetadata, r.resultExtras,
- r.partialResult.collectedResult, msg.frame_number);
+ r.partialResult.collectedResult, msg.frame_number,
+ r.hasInputBuffer);
returnOutputBuffers(r.pendingOutputBuffers.array(),
r.pendingOutputBuffers.size(), r.shutterTimestamp);
r.pendingOutputBuffers.clear();
@@ -2669,7 +2718,6 @@ bool Camera3Device::RequestThread::threadLoop() {
// Fill in buffers
if (nextRequest->mInputStream != NULL) {
- request.input_buffer = &inputBuffer;
res = nextRequest->mInputStream->getInputBuffer(&inputBuffer);
if (res != OK) {
// Can't get input buffer from gralloc queue - this could be due to
@@ -2686,6 +2734,7 @@ bool Camera3Device::RequestThread::threadLoop() {
cleanUpFailedRequest(request, nextRequest, outputBuffers);
return true;
}
+ request.input_buffer = &inputBuffer;
totalNumBuffers += 1;
} else {
request.input_buffer = NULL;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index a77548d..b08ba81 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -116,6 +116,8 @@ class Camera3Device :
virtual status_t deleteReprocessStream(int id);
virtual status_t configureStreams();
+ virtual status_t getInputBufferProducer(
+ sp<IGraphicBufferProducer> *producer);
virtual status_t createDefaultRequest(int templateId, CameraMetadata *request);
@@ -179,6 +181,14 @@ class Camera3Device :
uint32_t mDeviceVersion;
+ struct Size {
+ uint32_t width;
+ uint32_t height;
+ Size(uint32_t w = 0, uint32_t h = 0) : width(w), height(h){}
+ };
+ // Map from format to size.
+ Vector<Size> mSupportedOpaqueInputSizes;
+
enum Status {
STATUS_ERROR,
STATUS_UNINITIALIZED,
@@ -324,11 +334,11 @@ class Camera3Device :
*/
bool tryLockSpinRightRound(Mutex& lock);
- struct Size {
- int width;
- int height;
- Size(int w, int h) : width(w), height(h){}
- };
+ /**
+ * Helper function to determine if an input size for implementation defined
+ * format is supported.
+ */
+ bool isOpaqueInputSizeSupported(uint32_t width, uint32_t height);
/**
* Helper function to get the largest Jpeg resolution (in area)
@@ -639,8 +649,10 @@ class Camera3Device :
Mutex mOutputLock;
/**** Scope for mOutputLock ****/
-
+ // the minimal frame number of the next non-reprocess result
uint32_t mNextResultFrameNumber;
+ // the minimal frame number of the next reprocess result
+ uint32_t mNextReprocessResultFrameNumber;
uint32_t mNextShutterFrameNumber;
List<CaptureResult> mResultQueue;
Condition mResultSignal;
@@ -669,7 +681,8 @@ class Camera3Device :
// partial results, and the frame number to the result queue.
void sendCaptureResult(CameraMetadata &pendingMetadata,
CaptureResultExtras &resultExtras,
- CameraMetadata &collectedPartialResult, uint32_t frameNumber);
+ CameraMetadata &collectedPartialResult, uint32_t frameNumber,
+ bool reprocess);
/**** Scope for mInFlightLock ****/
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index 6bf671e..fa97e57 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -65,8 +65,8 @@ status_t Camera3InputStream::getInputBufferLocked(
assert(mConsumer != 0);
BufferItem bufferItem;
- res = mConsumer->acquireBuffer(&bufferItem, /*waitForFence*/false);
+ res = mConsumer->acquireBuffer(&bufferItem, /*waitForFence*/false);
if (res != OK) {
ALOGE("%s: Stream %d: Can't acquire next output buffer: %s (%d)",
__FUNCTION__, mId, strerror(-res), res);
@@ -162,6 +162,21 @@ status_t Camera3InputStream::returnInputBufferLocked(
return returnAnyBufferLocked(buffer, /*timestamp*/0, /*output*/false);
}
+status_t Camera3InputStream::getInputBufferProducerLocked(
+ sp<IGraphicBufferProducer> *producer) {
+ ATRACE_CALL();
+
+ if (producer == NULL) {
+ return BAD_VALUE;
+ } else if (mProducer == NULL) {
+ ALOGE("%s: No input stream is configured");
+ return INVALID_OPERATION;
+ }
+
+ *producer = mProducer;
+ return OK;
+}
+
status_t Camera3InputStream::disconnectLocked() {
status_t res;
@@ -212,10 +227,17 @@ status_t Camera3InputStream::configureQueueLocked() {
res = producer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers);
if (res != OK || minUndequeuedBuffers < 0) {
ALOGE("%s: Stream %d: Could not query min undequeued buffers (error %d, bufCount %d)",
- __FUNCTION__, mId, res, minUndequeuedBuffers);
+ __FUNCTION__, mId, res, minUndequeuedBuffers);
return res;
}
size_t minBufs = static_cast<size_t>(minUndequeuedBuffers);
+
+ if (camera3_stream::max_buffers == 0) {
+ ALOGE("%s: %d: HAL sets max_buffer to 0. Must be at least 1.",
+ __FUNCTION__, __LINE__);
+ return INVALID_OPERATION;
+ }
+
/*
* We promise never to 'acquire' more than camera3_stream::max_buffers
* at any one time.
@@ -232,6 +254,8 @@ status_t Camera3InputStream::configureQueueLocked() {
mConsumer = new BufferItemConsumer(consumer, camera3_stream::usage,
mTotalBufferCount);
mConsumer->setName(String8::format("Camera3-InputStream-%d", mId));
+
+ mProducer = producer;
}
res = mConsumer->setDefaultBufferSize(camera3_stream::width,
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.h b/services/camera/libcameraservice/device3/Camera3InputStream.h
index fd17f4f..7ba36c9 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.h
@@ -49,6 +49,7 @@ class Camera3InputStream : public Camera3IOStreamBase {
private:
sp<BufferItemConsumer> mConsumer;
+ sp<IGraphicBufferProducer> mProducer;
Vector<BufferItem> mBuffersInFlight;
/**
@@ -68,6 +69,8 @@ class Camera3InputStream : public Camera3IOStreamBase {
virtual status_t getInputBufferLocked(camera3_stream_buffer *buffer);
virtual status_t returnInputBufferLocked(
const camera3_stream_buffer &buffer);
+ virtual status_t getInputBufferProducerLocked(
+ sp<IGraphicBufferProducer> *producer);
virtual status_t disconnectLocked();
virtual status_t configureQueueLocked();
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 0c739e9..8d9b360 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -396,8 +396,22 @@ status_t Camera3OutputStream::getEndpointUsage(uint32_t *usage) {
int32_t u = 0;
res = mConsumer->query(mConsumer.get(),
NATIVE_WINDOW_CONSUMER_USAGE_BITS, &u);
- *usage = u;
+ // If an opaque output stream's endpoint is ImageReader, add
+ // GRALLOC_USAGE_HW_CAMERA_ZSL to the usage so HAL knows it will be used
+ // for the ZSL use case.
+ // Assume it's for ImageReader if the consumer usage doesn't have any of these bits set:
+ // 1. GRALLOC_USAGE_HW_TEXTURE
+ // 2. GRALLOC_USAGE_HW_RENDER
+ // 3. GRALLOC_USAGE_HW_COMPOSER
+ // 4. GRALLOC_USAGE_HW_VIDEO_ENCODER
+ if (camera3_stream::format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
+ (u & (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER |
+ GRALLOC_USAGE_HW_VIDEO_ENCODER)) == 0) {
+ u |= GRALLOC_USAGE_HW_CAMERA_ZSL;
+ }
+
+ *usage = u;
return res;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 4acbce3..d3c5cc3 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -346,6 +346,13 @@ status_t Camera3Stream::returnInputBuffer(const camera3_stream_buffer &buffer) {
return res;
}
+status_t Camera3Stream::getInputBufferProducer(sp<IGraphicBufferProducer> *producer) {
+ ATRACE_CALL();
+ Mutex::Autolock l(mLock);
+
+ return getInputBufferProducerLocked(producer);
+}
+
void Camera3Stream::fireBufferListenersLocked(
const camera3_stream_buffer& /*buffer*/, bool acquired, bool output) {
List<wp<Camera3StreamBufferListener> >::iterator it, end;
@@ -505,6 +512,10 @@ status_t Camera3Stream::returnInputBufferLocked(
ALOGE("%s: This type of stream does not support input", __FUNCTION__);
return INVALID_OPERATION;
}
+status_t Camera3Stream::getInputBufferProducerLocked(sp<IGraphicBufferProducer> *producer) {
+ ALOGE("%s: This type of stream does not support input", __FUNCTION__);
+ return INVALID_OPERATION;
+}
void Camera3Stream::addBufferListener(
wp<Camera3StreamBufferListener> listener) {
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index aba27fe..e89361e 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -205,6 +205,10 @@ class Camera3Stream :
*/
status_t returnInputBuffer(const camera3_stream_buffer &buffer);
+ // get the buffer producer of the input buffer queue.
+ // only apply to input streams.
+ status_t getInputBufferProducer(sp<IGraphicBufferProducer> *producer);
+
/**
* Whether any of the stream's buffers are currently in use by the HAL,
* including buffers that have been returned but not yet had their
@@ -285,6 +289,9 @@ class Camera3Stream :
virtual status_t returnInputBufferLocked(
const camera3_stream_buffer &buffer);
virtual bool hasOutstandingBuffersLocked() const = 0;
+ // Get the buffer producer of the input buffer queue. Only apply to input streams.
+ virtual status_t getInputBufferProducerLocked(sp<IGraphicBufferProducer> *producer);
+
// Can return -ENOTCONN when we are already disconnected (not an error)
virtual status_t disconnectLocked() = 0;
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index da989cd..ea90dd9 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -128,6 +128,13 @@ class Camera3StreamInterface : public virtual RefBase {
virtual status_t returnInputBuffer(const camera3_stream_buffer &buffer) = 0;
/**
+ * Get the buffer producer of the input buffer queue.
+ *
+ * This method only applies to input streams.
+ */
+ virtual status_t getInputBufferProducer(sp<IGraphicBufferProducer> *producer) = 0;
+
+ /**
* Whether any of the stream's buffers are currently in use by the HAL,
* including buffers that have been returned but not yet had their
* release fence signaled.