Add support for dynamic shared output surfaces
The Camera API needs to support the dynamic attach/detach of extra
output surfaces to a given camera stream.
Bug: 63912484
Change-Id: I18809aea31f78fb9e125bd18b58951ade4fad3c5
diff --git a/camera/ndk/impl/ACameraCaptureSession.cpp b/camera/ndk/impl/ACameraCaptureSession.cpp
index b9c159d..6d1d5ce 100644
--- a/camera/ndk/impl/ACameraCaptureSession.cpp
+++ b/camera/ndk/impl/ACameraCaptureSession.cpp
@@ -148,6 +148,23 @@
return ret;
}
+camera_status_t ACameraCaptureSession::updateOutputConfiguration(ACaptureSessionOutput *output) {
+ sp<CameraDevice> dev = getDeviceSp();
+ if (dev == nullptr) {
+ ALOGE("Error: Device associated with session %p has been closed!", this);
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+
+ camera_status_t ret;
+ dev->lockDeviceForSessionOps();
+ {
+ Mutex::Autolock _l(mSessionLock);
+ ret = dev->updateOutputConfiguration(output);
+ }
+ dev->unlockDevice();
+ return ret;
+}
+
ACameraDevice*
ACameraCaptureSession::getDevice() {
Mutex::Autolock _l(mSessionLock);
diff --git a/camera/ndk/impl/ACameraCaptureSession.h b/camera/ndk/impl/ACameraCaptureSession.h
index 339c665..a2068e7 100644
--- a/camera/ndk/impl/ACameraCaptureSession.h
+++ b/camera/ndk/impl/ACameraCaptureSession.h
@@ -24,7 +24,8 @@
using namespace android;
struct ACaptureSessionOutput {
- explicit ACaptureSessionOutput(ANativeWindow* window) : mWindow(window) {};
+ explicit ACaptureSessionOutput(ANativeWindow* window, bool isShared = false) :
+ mWindow(window), mIsShared(isShared) {};
bool operator == (const ACaptureSessionOutput& other) const {
return mWindow == other.mWindow;
@@ -40,6 +41,8 @@
}
ANativeWindow* mWindow;
+ std::set<ANativeWindow *> mSharedWindows;
+ bool mIsShared;
int mRotation = CAMERA3_STREAM_ROTATION_0;
};
@@ -89,6 +92,8 @@
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId);
+ camera_status_t updateOutputConfiguration(ACaptureSessionOutput *output);
+
ACameraDevice* getDevice();
private:
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 907802c..9ce0ac8 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -289,6 +289,82 @@
return ACAMERA_OK;
}
+camera_status_t CameraDevice::updateOutputConfiguration(ACaptureSessionOutput *output) {
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ return ret;
+ }
+
+ if (output == nullptr) {
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ if (!output->mIsShared) {
+ ALOGE("Error output configuration is not shared");
+ return ACAMERA_ERROR_INVALID_OPERATION;
+ }
+
+ int32_t streamId = -1;
+ for (auto& kvPair : mConfiguredOutputs) {
+ if (kvPair.second.first == output->mWindow) {
+ streamId = kvPair.first;
+ break;
+ }
+ }
+ if (streamId < 0) {
+ ALOGE("Error: Invalid output configuration");
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ sp<IGraphicBufferProducer> iGBP(nullptr);
+ ret = getIGBPfromAnw(output->mWindow, iGBP);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera device %s failed to extract graphic producer from native window",
+ getId());
+ return ret;
+ }
+
+ OutputConfiguration outConfig(iGBP, output->mRotation, OutputConfiguration::INVALID_SET_ID,
+ true);
+
+ for (auto& anw : output->mSharedWindows) {
+ ret = getIGBPfromAnw(anw, iGBP);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera device %s failed to extract graphic producer from native window",
+ getId());
+ return ret;
+ }
+ outConfig.addGraphicProducer(iGBP);
+ }
+
+ auto remoteRet = mRemote->updateOutputConfiguration(streamId, outConfig);
+ if (!remoteRet.isOk()) {
+ switch (remoteRet.serviceSpecificErrorCode()) {
+ case hardware::ICameraService::ERROR_INVALID_OPERATION:
+ ALOGE("Camera device %s invalid operation: %s", getId(),
+ remoteRet.toString8().string());
+ return ACAMERA_ERROR_INVALID_OPERATION;
+ break;
+ case hardware::ICameraService::ERROR_ALREADY_EXISTS:
+ ALOGE("Camera device %s output surface already exists: %s", getId(),
+ remoteRet.toString8().string());
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ break;
+ case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
+ ALOGE("Camera device %s invalid input argument: %s", getId(),
+ remoteRet.toString8().string());
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ break;
+ default:
+ ALOGE("Camera device %s failed to add shared output: %s", getId(),
+ remoteRet.toString8().string());
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+ }
+
+ return ACAMERA_OK;
+}
+
camera_status_t
CameraDevice::allocateCaptureRequest(
const ACaptureRequest* request, /*out*/sp<CaptureRequest>& outReq) {
@@ -540,7 +616,8 @@
return ret;
}
outputSet.insert(std::make_pair(
- anw, OutputConfiguration(iGBP, outConfig.mRotation)));
+ anw, OutputConfiguration(iGBP, outConfig.mRotation,
+ OutputConfiguration::INVALID_SET_ID, outConfig.mIsShared)));
}
auto addSet = outputSet;
std::vector<int> deleteList;
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 6ed3881..23cc1a1 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -36,7 +36,8 @@
#include <camera/camera2/OutputConfiguration.h>
#include <camera/camera2/CaptureRequest.h>
-#include <camera/NdkCameraDevice.h>
+#include <camera/NdkCameraManager.h>
+#include <camera/NdkCameraCaptureSession.h>
#include "ACameraMetadata.h"
namespace android {
@@ -122,6 +123,8 @@
/*out*/int* captureSequenceId,
bool isRepeating);
+ camera_status_t updateOutputConfiguration(ACaptureSessionOutput *output);
+
static camera_status_t allocateCaptureRequest(
const ACaptureRequest* request, sp<CaptureRequest>& outReq);