summaryrefslogtreecommitdiffstats
path: root/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/camera/libcameraservice/api2/CameraDeviceClient.cpp')
-rw-r--r--services/camera/libcameraservice/api2/CameraDeviceClient.cpp194
1 files changed, 165 insertions, 29 deletions
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 6a1ee44..bf1692d 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -65,13 +65,14 @@ CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
int servicePid) :
Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, cameraFacing, clientPid, clientUid, servicePid),
+ mInputStream(),
mRequestIdCounter(0) {
ATRACE_CALL();
ALOGI("CameraDeviceClient %d: Opened", cameraId);
}
-status_t CameraDeviceClient::initialize(camera_module_t *module)
+status_t CameraDeviceClient::initialize(CameraModule *module)
{
ATRACE_CALL();
status_t res;
@@ -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,24 +331,27 @@ 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;
}
-status_t CameraDeviceClient::createStream(int width, int height, int format,
- const sp<IGraphicBufferProducer>& bufferProducer)
+status_t CameraDeviceClient::createStream(const OutputConfiguration &outputConfiguration)
{
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);
+
+ sp<IGraphicBufferProducer> bufferProducer = outputConfiguration.getGraphicBufferProducer();
if (bufferProducer == NULL) {
ALOGE("%s: bufferProducer must not be null", __FUNCTION__);
return BAD_VALUE;
@@ -370,7 +397,8 @@ status_t CameraDeviceClient::createStream(int width, int height, int format,
sp<IBinder> binder = IInterface::asBinder(bufferProducer);
sp<ANativeWindow> anw = new Surface(bufferProducer, useAsync);
- // TODO: remove w,h,f since we are ignoring them
+ int width, height, format;
+ android_dataspace dataSpace;
if ((res = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, &width)) != OK) {
ALOGE("%s: Camera %d: Failed to query Surface width", __FUNCTION__,
@@ -387,6 +415,12 @@ status_t CameraDeviceClient::createStream(int width, int height, int format,
mCameraId);
return res;
}
+ if ((res = anw->query(anw.get(), NATIVE_WINDOW_DEFAULT_DATASPACE,
+ reinterpret_cast<int*>(&dataSpace))) != OK) {
+ ALOGE("%s: Camera %d: Failed to query Surface dataSpace", __FUNCTION__,
+ mCameraId);
+ return res;
+ }
// FIXME: remove this override since the default format should be
// IMPLEMENTATION_DEFINED. b/9487482
@@ -399,14 +433,17 @@ status_t CameraDeviceClient::createStream(int width, int height, int format,
// Round dimensions to the nearest dimensions available for this format
if (flexibleConsumer && !CameraDeviceClient::roundBufferDimensionNearest(width, height,
- format, mDevice->info(), /*out*/&width, /*out*/&height)) {
+ format, dataSpace, mDevice->info(), /*out*/&width, /*out*/&height)) {
ALOGE("%s: No stream configurations with the format %#x defined, failed to create stream.",
__FUNCTION__, format);
return BAD_VALUE;
}
int streamId = -1;
- res = mDevice->createStream(anw, width, height, format, &streamId);
+ res = mDevice->createStream(anw, width, height, format, dataSpace,
+ static_cast<camera3_stream_rotation_t>
+ (outputConfiguration.getRotation()),
+ &streamId);
if (res == OK) {
mStreamMap.add(binder, streamId);
@@ -440,11 +477,65 @@ status_t CameraDeviceClient::createStream(int width, int height, int format,
}
+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, const CameraMetadata& info,
+ int32_t format, android_dataspace dataSpace, const CameraMetadata& info,
/*out*/int32_t* outWidth, /*out*/int32_t* outHeight) {
camera_metadata_ro_entry streamConfigs =
+ (dataSpace == HAL_DATASPACE_DEPTH) ?
+ info.find(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS) :
info.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
int32_t bestWidth = -1;
@@ -580,25 +671,65 @@ status_t CameraDeviceClient::flush(int64_t* lastFrameNumber) {
return mDevice->flush(lastFrameNumber);
}
+status_t CameraDeviceClient::prepare(int streamId) {
+ ATRACE_CALL();
+ ALOGV("%s", __FUNCTION__);
+
+ status_t res = OK;
+ if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
+
+ Mutex::Autolock icl(mBinderSerializationLock);
+
+ // Guard against trying to prepare non-created streams
+ ssize_t index = NAME_NOT_FOUND;
+ 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;
+ }
+
+ // Also returns BAD_VALUE if stream ID was not valid
+ res = mDevice->prepare(streamId);
+
+ if (res == BAD_VALUE) {
+ ALOGE("%s: Camera %d: Unexpected BAD_VALUE when preparing stream, but we"
+ " already checked and the stream ID (%d) should be valid.",
+ __FUNCTION__, mCameraId, streamId);
+ }
+
+ return res;
+}
+
status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) {
String8 result;
result.appendFormat("CameraDeviceClient[%d] (%p) dump:\n",
mCameraId,
(getRemoteCallback() != NULL ?
IInterface::asBinder(getRemoteCallback()).get() : NULL) );
- result.appendFormat(" Current client: %s (PID %d, UID %u)\n",
- String8(mClientPackageName).string(),
- mClientPid, mClientUid);
+ result.appendFormat(" Current client UID %u\n", mClientUid);
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
@@ -635,8 +766,13 @@ void CameraDeviceClient::notifyShutter(const CaptureResultExtras& resultExtras,
}
}
-// TODO: refactor the code below this with IProCameraUser.
-// it's 100% copy-pasted, so lets not change it right now to make it easier.
+void CameraDeviceClient::notifyPrepared(int streamId) {
+ // Thread safe. Don't bother locking.
+ sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
+ if (remoteCb != 0) {
+ remoteCb->onPrepared(streamId);
+ }
+}
void CameraDeviceClient::detachDevice() {
if (mDevice == 0) return;