/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_HARDWARE_PRO_CAMERA_H #define ANDROID_HARDWARE_PRO_CAMERA_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct camera_metadata; namespace android { // All callbacks on this class are concurrent // (they come from separate threads) class ProCameraListener : virtual public RefBase { public: virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0; // Lock has been acquired. Write operations now available. virtual void onLockAcquired() = 0; // Lock has been released with exclusiveUnlock. virtual void onLockReleased() = 0; // Lock has been stolen by another client. virtual void onLockStolen() = 0; // Lock free. virtual void onTriggerNotify(int32_t msgType, int32_t ext1, int32_t ext2) = 0; // onFrameAvailable and OnResultReceived can come in with any order, // use android.sensor.timestamp and LockedBuffer.timestamp to correlate them /** * A new metadata buffer has been received. * -- Ownership of request passes on to the callee, free with * free_camera_metadata. */ virtual void onResultReceived(int32_t frameId, camera_metadata* result) = 0; // TODO: make onFrameAvailable pure virtual // A new frame buffer has been received for this stream. // -- This callback only fires for createStreamCpu streams // -- A buffer may be obtained by calling cpuConsumer->lockNextBuffer // -- Use buf.timestamp to correlate with result's android.sensor.timestamp // -- The buffer should be accessed with CpuConsumer::lockNextBuffer // and CpuConsumer::unlockBuffer virtual void onFrameAvailable(int /*streamId*/, const sp& /*cpuConsumer*/) { } }; class ProCamera; template <> struct CameraTraits { typedef ProCameraListener TCamListener; typedef IProCameraUser TCamUser; typedef IProCameraCallbacks TCamCallbacks; typedef status_t (ICameraService::*TCamConnectService)(const sp&, int, const String16&, int, /*out*/ sp&); static TCamConnectService fnConnectService; }; class ProCamera : public CameraBase, public BnProCameraCallbacks { public: /** * Connect a shared camera. By default access is restricted to read only * (Lock free) operations. To be able to submit custom requests a lock needs * to be acquired with exclusive[Try]Lock. */ static sp connect(int cameraId); virtual ~ProCamera(); /** * Exclusive Locks: * - We may request exclusive access to a camera if no other * clients are using the camera. This works as a traditional * client, writing/reading any camera state. * - An application opening the camera (a regular 'Camera') will * always steal away the exclusive lock from a ProCamera, * this will call onLockReleased. * - onLockAcquired will be called again once it is possible * to again exclusively lock the camera. * */ /** * All exclusiveLock/unlock functions are asynchronous. The remote endpoint * shall not block while waiting to acquire the lock. Instead the lock * notifications will come in asynchronously on the listener. */ /** * Attempt to acquire the lock instantly (non-blocking) * - If this succeeds, you do not need to wait for onLockAcquired * but the event will still be fired * * Returns -EBUSY if already locked. 0 on success. */ status_t exclusiveTryLock(); // always returns 0. wait for onLockAcquired before lock is acquired. status_t exclusiveLock(); // release a lock if we have one, or cancel the lock request. status_t exclusiveUnlock(); // exclusive lock = do whatever we want. no lock = read only. bool hasExclusiveLock(); /** * < 0 error, >= 0 the request ID. streaming to have the request repeat * until cancelled. * The request queue is flushed when a lock is released or stolen * if not locked will return PERMISSION_DENIED */ int submitRequest(const struct camera_metadata* metadata, bool streaming = false); // if not locked will return PERMISSION_DENIED, BAD_VALUE if requestId bad status_t cancelRequest(int requestId); /** * Ask for a stream to be enabled. * Lock free. Service maintains counter of streams. */ status_t requestStream(int streamId); // TODO: remove requestStream, its useless. /** * Delete a stream. * Lock free. * * NOTE: As a side effect this cancels ALL streaming requests. * * Errors: BAD_VALUE if unknown stream ID. * PERMISSION_DENIED if the stream wasn't yours */ status_t deleteStream(int streamId); /** * Create a new HW stream, whose sink will be the window. * Lock free. Service maintains counter of streams. * Errors: -EBUSY if too many streams created */ status_t createStream(int width, int height, int format, const sp& surface, /*out*/ int* streamId); /** * Create a new HW stream, whose sink will be the SurfaceTexture. * Lock free. Service maintains counter of streams. * Errors: -EBUSY if too many streams created */ status_t createStream(int width, int height, int format, const sp& bufferProducer, /*out*/ int* streamId); status_t createStreamCpu(int width, int height, int format, int heapCount, /*out*/ sp* cpuConsumer, int* streamId); status_t createStreamCpu(int width, int height, int format, int heapCount, bool synchronousMode, /*out*/ sp* cpuConsumer, int* streamId); // Create a request object from a template. status_t createDefaultRequest(int templateId, /*out*/ camera_metadata** request) const; // Get static camera metadata camera_metadata* getCameraInfo(int cameraId); // Blocks until a frame is available (CPU streams only) // - Obtain the frame data by calling CpuConsumer::lockNextBuffer // - Release the frame data after use with CpuConsumer::unlockBuffer // Return value: // - >0 - number of frames available to be locked // - <0 - error (refer to error codes) // Error codes: // -ETIMEDOUT if it took too long to get a frame int waitForFrameBuffer(int streamId); // Blocks until a metadata result is available // - Obtain the metadata by calling consumeFrameMetadata() // Error codes: // -ETIMEDOUT if it took too long to get a frame status_t waitForFrameMetadata(); // Get the latest metadata. This is destructive. // - Calling this repeatedly will produce empty metadata objects. // - Use waitForFrameMetadata to sync until new data is available. CameraMetadata consumeFrameMetadata(); // Convenience method to drop frame buffers (CPU streams only) // Return values: // >=0 - number of frames dropped (up to count) // <0 - error code // Error codes: // BAD_VALUE - invalid streamId or count passed int dropFrameBuffer(int streamId, int count); protected: //////////////////////////////////////////////////////// // IProCameraCallbacks implementation //////////////////////////////////////////////////////// virtual void notifyCallback(int32_t msgType, int32_t ext, int32_t ext2); virtual void onLockStatusChanged( IProCameraCallbacks::LockStatus newLockStatus); virtual void onResultReceived(int32_t requestId, camera_metadata* result); private: ProCamera(int cameraId); class ProFrameListener : public CpuConsumer::FrameAvailableListener { public: ProFrameListener(wp camera, int streamID) { mCamera = camera; mStreamId = streamID; } protected: virtual void onFrameAvailable() { sp c = mCamera.promote(); if (c.get() != NULL) { c->onFrameAvailable(mStreamId); } } private: wp mCamera; int mStreamId; }; friend class ProFrameListener; struct StreamInfo { StreamInfo(int streamId) { this->streamID = streamId; cpuStream = false; frameReady = 0; } StreamInfo() { streamID = -1; cpuStream = false; } int streamID; bool cpuStream; sp cpuConsumer; bool synchronousMode; sp frameAvailableListener; sp stc; int frameReady; }; Condition mWaitCondition; Mutex mWaitMutex; static const nsecs_t mWaitTimeout = 1000000000; // 1sec KeyedVector mStreams; bool mMetadataReady; CameraMetadata mLatestMetadata; void onFrameAvailable(int streamId); StreamInfo& getStreamInfo(int streamId); friend class CameraBase; }; }; // namespace android #endif