Camera NDK library: capture session implementation
Bug: 23012001
Change-Id: I3fd93205dcf1b9ed5a947cb944919eb531f219fc
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 061175c..b73e621 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -17,26 +17,35 @@
#define _ACAMERA_DEVICE_H
#include <memory>
+#include <map>
+#include <set>
#include <atomic>
#include <utils/StrongPointer.h>
#include <utils/Mutex.h>
#include <utils/String8.h>
+#include <utils/List.h>
+#include <utils/Vector.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AHandler.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <camera/CaptureResult.h>
#include <camera/camera2/ICameraDeviceCallbacks.h>
#include <camera/camera2/ICameraDeviceUser.h>
+#include <camera/camera2/OutputConfiguration.h>
+#include <camera/camera2/CaptureRequest.h>
#include <NdkCameraDevice.h>
#include "ACameraMetadata.h"
-
using namespace android;
namespace android {
-struct CameraDevice final : public RefBase {
+// Wrap ACameraCaptureFailure so it can be ref-counter
+struct CameraCaptureFailure : public RefBase, public ACameraCaptureFailure {};
+
+class CameraDevice final : public RefBase {
public:
CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
std::unique_ptr<ACameraMetadata> chars,
@@ -49,6 +58,11 @@
ACameraDevice_request_template templateId,
ACaptureRequest** request) const;
+ camera_status_t createCaptureSession(
+ const ACaptureSessionOutputContainer* outputs,
+ const ACameraCaptureSession_stateCallbacks* callbacks,
+ /*out*/ACameraCaptureSession** session);
+
// Callbacks from camera service
class ServiceCallback : public BnCameraDeviceCallbacks {
public:
@@ -69,10 +83,60 @@
// Camera device is only functional after remote being set
void setRemoteDevice(sp<ICameraDeviceUser> remote);
+ inline ACameraDevice* getWrapper() const { return mWrapper; };
+
private:
- void disconnectLocked(); // disconnect from camera service
+ friend ACameraCaptureSession;
camera_status_t checkCameraClosedOrErrorLocked() const;
+ // device goes into fatal error state after this
+ void setCameraDeviceErrorLocked(camera_status_t error);
+
+ void disconnectLocked(); // disconnect from camera service
+
+ camera_status_t stopRepeatingLocked();
+
+ camera_status_t waitUntilIdleLocked();
+
+
+ camera_status_t captureLocked(sp<ACameraCaptureSession> session,
+ /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId);
+
+ camera_status_t setRepeatingRequestsLocked(sp<ACameraCaptureSession> session,
+ /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId);
+
+ camera_status_t submitRequestsLocked(
+ sp<ACameraCaptureSession> session,
+ /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*out*/int* captureSequenceId,
+ bool isRepeating);
+
+ static camera_status_t allocateCaptureRequest(
+ const ACaptureRequest* request, sp<CaptureRequest>& outReq);
+
+ static ACaptureRequest* allocateACaptureRequest(sp<CaptureRequest>& req);
+ static void freeACaptureRequest(ACaptureRequest*);
+
+ // only For session to hold device lock
+ // Always grab device lock before grabbing session lock
+ void lockDeviceForSessionOps() const { mDeviceLock.lock(); };
+ void unlockDevice() const { mDeviceLock.unlock(); };
+
+ // For capture session to notify its end of life
+ void notifySessionEndOfLifeLocked(ACameraCaptureSession* session);
+
+ camera_status_t configureStreamsLocked(const ACaptureSessionOutputContainer* outputs);
+
+ static camera_status_t getIGBPfromSessionOutput(
+ const ACaptureSessionOutput& config, sp<IGraphicBufferProducer>& out);
+
+ static camera_status_t getSurfaceFromANativeWindow(
+ ANativeWindow* anw, sp<Surface>& out);
mutable Mutex mDeviceLock;
const String8 mCameraId; // Camera ID
@@ -81,6 +145,9 @@
const sp<ServiceCallback> mServiceCallback;
ACameraDevice* mWrapper;
+ // stream id -> OutputConfiguration map
+ std::map<int, OutputConfiguration> mConfiguredOutputs;
+
// TODO: maybe a bool will suffice for synchronous implementation?
std::atomic_bool mClosing;
inline bool isClosed() { return mClosing; }
@@ -92,6 +159,8 @@
const CaptureResultExtras& resultExtras);
bool mIdle;
+ // This will avoid a busy session being deleted before it's back to idle state
+ sp<ACameraCaptureSession> mBusySession;
sp<ICameraDeviceUser> mRemote;
@@ -99,13 +168,29 @@
sp<ALooper> mCbLooper;
// definition of handler and message
enum {
- kWhatOnDisconnected,
- kWhatOnError
+ // Device state callbacks
+ kWhatOnDisconnected, // onDisconnected
+ kWhatOnError, // onError
+ // Session state callbacks
+ kWhatSessionStateCb, // onReady, onActive
+ // Capture callbacks
+ kWhatCaptureStart, // onCaptureStarted
+ kWhatCaptureResult, // onCaptureProgressed, onCaptureCompleted
+ kWhatCaptureFail, // onCaptureFailed
+ kWhatCaptureSeqEnd, // onCaptureSequenceCompleted
+ kWhatCaptureSeqAbort // onCaptureSequenceAborted
};
static const char* kContextKey;
static const char* kDeviceKey;
static const char* kErrorCodeKey;
- static const char* kCallbackKey;
+ static const char* kCallbackFpKey;
+ static const char* kSessionSpKey;
+ static const char* kCaptureRequestKey;
+ static const char* kTimeStampKey;
+ static const char* kCaptureResultKey;
+ static const char* kCaptureFailureKey;
+ static const char* kSequenceIdKey;
+ static const char* kFrameNumberKey;
class CallbackHandler : public AHandler {
public:
CallbackHandler() {}
@@ -113,10 +198,65 @@
};
sp<CallbackHandler> mHandler;
- inline ACameraDevice* getWrapper() { return mWrapper; };
+ /***********************************
+ * Capture session related members *
+ ***********************************/
+ // The current active session
+ ACameraCaptureSession* mCurrentSession = nullptr;
+ int mNextSessionId = 0;
// TODO: might need another looper/handler to handle callbacks from service
+ static const int REQUEST_ID_NONE = -1;
+ int mRepeatingSequenceId = REQUEST_ID_NONE;
+
+ // sequence id -> last frame number map
+ std::map<int, int64_t> mSequenceLastFrameNumberMap;
+
+ struct CallbackHolder {
+ CallbackHolder(sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_captureCallbacks* cbs);
+
+ static ACameraCaptureSession_captureCallbacks fillCb(
+ ACameraCaptureSession_captureCallbacks* cbs) {
+ if (cbs != nullptr) {
+ return *cbs;
+ }
+ return { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
+ }
+
+ sp<ACameraCaptureSession> mSession;
+ Vector<sp<CaptureRequest> > mRequests;
+ const bool mIsRepeating;
+ ACameraCaptureSession_captureCallbacks mCallbacks;
+ };
+ // sequence id -> callbacks map
+ std::map<int, CallbackHolder> mSequenceCallbackMap;
+
+ static const int64_t NO_FRAMES_CAPTURED = -1;
+ class FrameNumberTracker {
+ public:
+ // TODO: Called in onResultReceived and onCaptureErrorLocked
+ void updateTracker(int64_t frameNumber, bool isError);
+ inline int64_t getCompletedFrameNumber() { return mCompletedFrameNumber; }
+ private:
+ void update();
+ void updateCompletedFrameNumber(int64_t frameNumber);
+
+ int64_t mCompletedFrameNumber = NO_FRAMES_CAPTURED;
+ List<int64_t> mSkippedFrameNumbers;
+ std::set<int64_t> mFutureErrorSet;
+ };
+ FrameNumberTracker mFrameNumberTracker;
+
+ void checkRepeatingSequenceCompleteLocked(const int sequenceId, const int64_t lastFrameNumber);
+ void checkAndFireSequenceCompleteLocked();
+
+ // Misc variables
+ int32_t mShadingMapSize[2]; // const after constructor
+ int32_t mPartialResultCount; // const after constructor
};
@@ -133,6 +273,9 @@
~ACameraDevice() {};
+ /*******************
+ * NDK public APIs *
+ *******************/
inline const char* getId() const { return mDevice->getId(); }
camera_status_t createCaptureRequest(
@@ -141,6 +284,16 @@
return mDevice->createCaptureRequest(templateId, request);
}
+ camera_status_t createCaptureSession(
+ const ACaptureSessionOutputContainer* outputs,
+ const ACameraCaptureSession_stateCallbacks* callbacks,
+ /*out*/ACameraCaptureSession** session) {
+ return mDevice->createCaptureSession(outputs, callbacks, session);
+ }
+
+ /***********************
+ * Device interal APIs *
+ ***********************/
inline sp<ICameraDeviceCallbacks> getServiceCallback() {
return mDevice->getServiceCallback();
};
@@ -151,7 +304,6 @@
}
private:
- // TODO: might need an API to give wp of mDevice to capture session
sp<CameraDevice> mDevice;
};