| /* |
| * 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 <utils/Timers.h> |
| #include <utils/KeyedVector.h> |
| #include <gui/IGraphicBufferProducer.h> |
| #include <system/camera.h> |
| #include <camera/IProCameraCallbacks.h> |
| #include <camera/IProCameraUser.h> |
| #include <camera/Camera.h> |
| #include <camera/CameraMetadata.h> |
| #include <gui/CpuConsumer.h> |
| |
| #include <gui/Surface.h> |
| |
| #include <utils/Condition.h> |
| #include <utils/Mutex.h> |
| |
| #include <camera/CameraBase.h> |
| |
| 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>& /*cpuConsumer*/) { |
| } |
| |
| }; |
| |
| class ProCamera; |
| |
| template <> |
| struct CameraTraits<ProCamera> |
| { |
| typedef ProCameraListener TCamListener; |
| typedef IProCameraUser TCamUser; |
| typedef IProCameraCallbacks TCamCallbacks; |
| }; |
| |
| class ProCamera : |
| public CameraBase<ProCamera>, |
| 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<ProCamera> 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>& 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<IGraphicBufferProducer>& bufferProducer, |
| /*out*/ |
| int* streamId); |
| status_t createStreamCpu(int width, int height, int format, |
| int heapCount, |
| /*out*/ |
| sp<CpuConsumer>* cpuConsumer, |
| int* streamId); |
| status_t createStreamCpu(int width, int height, int format, |
| int heapCount, |
| bool synchronousMode, |
| /*out*/ |
| sp<CpuConsumer>* 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 frameId, |
| camera_metadata* result); |
| private: |
| ProCamera(int cameraId); |
| |
| class ProFrameListener : public CpuConsumer::FrameAvailableListener { |
| public: |
| ProFrameListener(wp<ProCamera> camera, int streamID) { |
| mCamera = camera; |
| mStreamId = streamID; |
| } |
| |
| protected: |
| virtual void onFrameAvailable() { |
| sp<ProCamera> c = mCamera.promote(); |
| if (c.get() != NULL) { |
| c->onFrameAvailable(mStreamId); |
| } |
| } |
| |
| private: |
| wp<ProCamera> 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> cpuConsumer; |
| bool synchronousMode; |
| sp<ProFrameListener> frameAvailableListener; |
| sp<Surface> stc; |
| int frameReady; |
| }; |
| |
| Condition mWaitCondition; |
| Mutex mWaitMutex; |
| static const nsecs_t mWaitTimeout = 1000000000; // 1sec |
| KeyedVector<int, StreamInfo> mStreams; |
| bool mMetadataReady; |
| CameraMetadata mLatestMetadata; |
| |
| void onFrameAvailable(int streamId); |
| |
| StreamInfo& getStreamInfo(int streamId); |
| |
| friend class CameraBase; |
| }; |
| |
| }; // namespace android |
| |
| #endif |